CM5: What would I lose by disabling contenteditable.pollSelection()?

I’m running into an issue with CM5 content being semirandomly skipped in a screenreader, and have tracked it down to the contenteditable.pollSelection() method.

If I were to add a user option to disable this polling entirely for compatibility, what functionality would be lost exactly?

NVDA appears to trigger a bunch of focus and blur events while reading, and that coupled with the setSelection() inside the polling method may be the issue, and disabling the polling does appear to fix it.

I haven’t been able to create a test case for it yet, and it may be specific to the running environment (electron).

This is used to keep the editor selection in sync with the DOM selection, and disabling it will cause the editor to fail to reflect things like touch selection in its actual selection state (which will then cause commands and such to act on the wrong selection).

So I guess we’ll have to add more hacks (or reuse existing hacks like ContentEditableInput.gracePeriod) to work around this issue somehow.


I’ve managed to isolate it to the active-line extension, and created a minimal reproduction (without electron or any other complications):

With NVDA, using the factory defaults (other than speech speed), this line skipping occurs when the editor is focused and then read in browse mode for the first time.

I believe this is happening when the lines (previously pre.CodeMirror-Line) are wrapped in a new div for the CodeMirror-activeline line class. The wrapper divs aren’t removed when the line class is removed, so on a second reading, all the lines will already be wrapped, and NVDA will read the line correctly

Since this addon just uses cm.addLineClass(), I imagine there are related issues in other places, but since this addon operates on selectionChange and on the current line, it’s more likely to cause the issue.

Is there a way that I could preemptively wrap all lines in this way, so that when the activeline class is applied later, it doesn’t cause this transformation on the current line being read?

Or any other suggestions, if you think this may be the wrong direction to look?

I’m adding an overlay mode that adds a line-background- class to every line (so lines aren’t being rewrapped on the fly when using the active-line addon).

This appears to solve the issue without having to add much uglier hacks for focusing or selection.

const BACKGROUND_TOKEN = 'line-background-forced'

CodeMirror.defineMode('forced_wrap',  () => ({
  token: stream => {
  blankLine: () => BACKGROUND_TOKEN

Would there be any possibility of switching your product to CodeMirror 6? That’s going to give you fundamentally better screen reader support. Version 5 is probably never going to get this all right.

I think I’ll need to, one way or another. It’ll be a huge undertaking.