slate: Using inside a contenteditable="false" is broken in Firefox

We noticed a bug in Firefox, rendering a node as follows is broken:

<div contenteditable="false">
  <input type="text" />
</div>

There are two things to note:

  1. Left/right arrow keys don’t move the caret
  2. Pressing a character key (or backspace) throws an error:

Permission denied to access property “nodeType”

I created a repository reproducing the error with Slate and a minimal setup: http://gabinaureche.com/slate-firefox-bug/

The error comes from isInEditor which tries to read window.getSelection().anchorNode.nodeType but anchorNode is “Restricted”.

This bug is reproducible without Slate, here’s a pretty simple scenario: https://jsfiddle.net/hsqebsk2/1/

I filed an issue to Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=1449936

Probably related to #843

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 1
  • Comments: 24 (6 by maintainers)

Most upvoted comments

Just wanted to outline how critical this is, as I’m not certain that’s clear.

This bug means projects that support Firefox, which is most projects, can’t use inputs in Slate, as Slate controls the contenteditable attributes within itself and I think they’re always false for void nodes.

Best repro of this bug is in Slate’s example site - try editing the YouTube video url in firefox: https://www.slatejs.org/#/embeds

I’m working on tracking down the commit where this broke - we ran into it by upgrading slate from ^0.30 to ^0.34 and slate-react from 0.10.11 to 0.12.9.

I’ve rolled back the regression that made inputs inside voids unable to be focused in all browsers, so this issue can remain for the Firefox case.

Hi @ianstormtaylor, it seems that this issue and #1926 are the same, perhaps we could merge them?

I’m also hoping that participants here would be willing to test the embeds example in other browsers and confirm broken behaviour. Would be more than happy to contribute if I knew where to start; this is a blocker for my project and, presumably, any project that has <input /> elements inside void blocks with the newer Slate releases.

This isn’t just a FireFox issue.

The inputs inside void blocks do not work on any of the browsers I’ve tried on macOS. This example: https://www.slatejs.org/#/embeds does not work (I can not change the contents of the input element on any of my browsers).

This can be worked around by using


<div contenteditable>
    <div contenteditable="false">
        <input contenteditable type="text" value="Some text content">
    </div>
</div>

Or by using the componentDidThrow() react event handler to keep these errors from crashing the editor.

I also don’t think this is a Slate bug.

The bug report on Firefox’s side was just marked as resolved. I wasn’t able to reproduce the bug in the two following scenarios, with Firefox 65:

So it does seem to be fixed. Could someone else confirm?

I was able to hunt this down in https://github.com/ianstormtaylor/slate/pull/2198.

Simply reverting this commit fixes the embed example and allows elements such as input elements within a void node to receives change, keydown, click, etc. events.

#2198 was intended to make copying behavior consistent for inline void with text and inline void without text. However, it mistakes void blocks as being inTheEditor.

@uipoptart Can this be implemented differently?

Happy to help too! I’ve read the Firefox bug report and it seems to me we’re reporting perfectly reasonable behaviour as a bug. It’s Chrome and other browsers that are just being more forgiving. @ianstormtaylor could you guide us to the part of the source code that requires this nested structure? #2178 appears to swallow the error. What would it look like never having an input inside a contenteditable=false i.e. making them siblings? I appreciate nesting is a major part of Slate but surely we could do this using siblings?

Thanks to #2178 , Firefox will no longer crashes. However, the inputs are nearly unusable, because you cannot move the cursor freely inside it, even by clicking somewhere.

Here is another error thrown when focusing the input:

Error: Permission denied to access property "window" index.js:25
isWindow                     index.js:25
getWindow                    index.js:39
findRange                    slate-react.es.js:1409
onEvent                      slate-react.es.js:2029
Content/</_this[handler]     slate-react.es.js:1936