Skip to content

Bug: List/ListItem Nodes From DOM results in invalid editor state  #3975

Closed

Description

@brianbolnick

I'm working on parsing HTML (from a headless editor) and converting it as the initial state for an editor. I'm getting what looks like a valid json obj back, but providing that value to the editor is giving me a Cannot call set() on a frozen Lexical node map error, thrown by the ListItemNode. I'm comparing what result I get from this process to the value I get from pasting the same html into an editor, and they look real similar, with small exceptions being the format and direction keys of some of the values.

Any ideas here? Maybe a bug with the headless editor? This only happens with the list/listitem nodes. Everything else seems to parse pretty smoothly.

Here's the full stack trace:

Lexical.dev.js:5445 Uncaught Error: Cannot call set() on a frozen Lexical node map
    at nodeMap.set (Lexical.dev.js:5445:1)
    at ListItemNode.getWritable (Lexical.dev.js:6257:1)
    at ListItemNode.setValue (LexicalList.dev.js:657:1)
    at updateChildrenListItemValue (LexicalList.dev.js:279:1)
    at ListItemNode.createDOM (LexicalList.dev.js:473:1)
    at createNode (Lexical.dev.js:1690:1)
    at createChildren (Lexical.dev.js:1772:1)
    at createChildrenWithDirection (Lexical.dev.js:1763:1)
    at createNode (Lexical.dev.js:1710:1)
    at createChildren (Lexical.dev.js:1772:1)

Lexical version: 0.8.1

Steps To Reproduce

  1. See example code below

Link to code example:
Here's a brief example of the process for debug purposes:

  const editor = createHeadlessEditor({
    nodes: [
      AutoLinkNode,
      HeadingNode,
      LinkNode,
      ListNode,
      ListItemNode
    ],
  });

  editor.update(() => {
    const dom = new JSDOM(htmlString);

    const nodes = $generateNodesFromDOM(editor, dom.window.document);
    const root = $getRoot();

    nodes.forEach((node) => {
      root.append(node);
    });
  });

  editor.registerUpdateListener(({ editorState }) => {
    editorState.read(() => {
      const lexicalStructure = JSON.stringify(editorState);
      // save to a db for later use
    });
  });

The current behavior

Returns a stringified state object that looks correct, but breaks when passed to an editor as initial state.

The expected behavior

It works :)

Activity

  1. thegreatercurve commented on Feb 27, 2023

    @thegreatercurve
    Contributor

    What happens if you set editable: true in the createHeadlessEditor config object? Although, that should be true by default.

  2. brianbolnick commented on Feb 27, 2023

    @brianbolnick
    Author

    What happens if you set editable: true in the createHeadlessEditor config object? Although, that should be true by default.

    Yeah, no luck there 😔

  3. brianbolnick commented on Feb 28, 2023

    @brianbolnick
    Author

    I think @thegreatercurve might be close to something, though. Not sure if it's a build issue or there's something else going on, but it looks like the issue is definitely related to the handleDEVOnlyPendingUpdateGuarantees function which is still being called. For instance looking at this guy in my actual node modules is getting built like this:

        // Make the editorState immutable
        editorState._readOnly = true;
        {
    	handleDEVOnlyPendingUpdateGuarantees(editorState);
        }
    

    Without the DEV check. This is in my local environment, but I also ran with a prod build and it's still getting called just to weed out that as a possibility. Is the dev check failing or is there some other build stage thats causing this to be called when it shouldn't be?

  4. brianbolnick commented on Feb 28, 2023

    @brianbolnick
    Author

    I think @thegreatercurve might be close to something, though. Not sure if it's a build issue or there's something else going on, but it looks like the issue is definitely related to the handleDEVOnlyPendingUpdateGuarantees function which is still being called. For instance looking at this guy in my actual node modules is getting built like this:

        // Make the editorState immutable
        editorState._readOnly = true;
        {
    	handleDEVOnlyPendingUpdateGuarantees(editorState);
        }
    

    Without the DEV check. This is in my local environment, but I also ran with a prod build and it's still getting called just to weed out that as a possibility. Is the dev check failing or is there some other build stage thats causing this to be called when it shouldn't be?

    Update: Found the reasoning... the published package still runs in dev mode based on the actual NODE_ENV running process, not on the actual build script which is what I had originally thought:

    const Lexical = process.env.NODE_ENV === 'development' ? require('./Lexical.dev.js') : require('./Lexical.prod.js')

    Running my server in prod mode bypasses this issue, but I'm wondering if this should be intended? Forgive my ignorance, but isn't a published NPM package considered "production" and should be treated as such when running in a project, regardless of its own environment? I'm going to have to run our app in prod mode every time moving forward with this now, which is kind of annoying. Any thoughts here?

  5. rferreira98 commented on Mar 3, 2023

    @rferreira98

    I have this similar issue when using lists (ListNodes & ListItemNodes) along with createEditor function.

  6. Boanerges1996 commented on Mar 3, 2023

    @Boanerges1996

    I am also having similar issue, @brianbolnick thanks for reporting it.

  7. acywatson commented on Mar 4, 2023

    @acywatson
    Contributor

    Running my server in prod mode bypasses this issue, but I'm wondering if this should be intended? Forgive my ignorance, but isn't a published NPM package considered "production" and should be treated as such when running in a project, regardless of its own environment? I'm going to have to run our app in prod mode every time moving forward with this now, which is kind of annoying. Any thoughts here?

    I think the DEV/PROD behavior is as intended, but that means there's probably a bug. Lexical throws these errors in DEV so you can catch them before sending them out to users. You should only be running the app in "PROD" when you would otherwise/normally do so.

    I don't see in your code where you're creating the editor with the the state after parsing it from HTML? Is the error being thrown in the update callback in your code above?

    UPDATE:

    Here's the fix: #4030 (or a fix, at least)

    You weren't doing anything wrong AFAICT

  8. brianbolnick commented on Mar 7, 2023

    @brianbolnick
    Author

    Thanks so much @acywatson!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions