Command insertNewlineAndIndent() causes a view bug, unless used with highlightActiveLine() extension

Okay, from the front I should say that I’m nearly positive that it’s not a bug in the library, I’m positive it’s the problem with my setup of CodeMirror.

I’m experiencing weird behaviour of the editor on mobile, and only in mobile view. If I use “Computer view” in my phone it works perfectly. If I enable normal “Phone view”, then it behaves wierdly.

I’ve made a regording, what I’m seeing is that:

  • When I press Enter on my mobile phone (0:14)
  • I see that newline is added to EditorState
  • But I see two lines in the view
  • Then I press Backspace, and the cursor in the view goes back, but there are now two new lines

On the recording there first string below the editor is JSON.stringify() of view.state.toString(), and the HTML below is view.contentDOM.innerHTML.

I have no idea what’s going on, I know I messed up some key bindings probably, but I don’t know what I did wrong. What can I do to fix this?

Here’s the recording (it’s public):Screen_Recording_20220208-133052_Chrome_1.mp4 - Google Drive

If this doesn’t happen in a plain setup, I guess the first step to debugging it is to simplify your setup piece by piece to see which extension/configuration causes the issue.

@marijn Okay, I think I narrowed it down.

In this line: https://github.com/codemirror/commands/blob/10369514e6b8062e25ee9c6bc618ab1f3c6c7b33/src/commands.ts#L635

You call

dispatch(state.update(changes, {scrollIntoView: true, userEvent: "input"}))

I tried debugging, and I looked up what changes was exactly, and when I passed it as an object literal, the bug disappeared. That lead me to believe that there’s probably something about the changes references that take action.

Here’s info for you. If you update this line with a deep-copy of changes:

dispatch(state.update(changes, {scrollIntoView: true, userEvent: "input"}))

to this line

changes = JSON.parse(JSON.stringify(changes));
dispatch(state.update(changes, {scrollIntoView: true, userEvent: "input"}))

the bug disappears.

There’s something about object references that messes it up. I don’t know what exactly, but with a hard copy of changes in newlineAndIndent it works perfectly.

Okay, if you change

{from, to, insert: Text.of(insert)}

to

{from, to, insert: insert}

in newlineAndIndent() then it works as well.

insert is an array, perhaps its reference is passed around unknowingly?

PS:
Updating to array spread doesn’t work :confused:

{from, to, insert: Text.of([...insert])}

insertNewlineAndIndent is what the default keymap binds to Enter. Is this also happening for you on a plain basicSetup configuration with no external code?

Okay, but if I use

import {EditorState} from '@codemirror/state';
import {EditorView, keymap} from '@codemirror/view';
import {defaultKeymap} from "@codemirror/commands";

export class Editor {
  constructor(parent) {
    const state = EditorState.create({
      doc: 'Two',
      extensions: [
        keymap.of([
          ...defaultKeymap,
        ])
      ]
    });
    new EditorView({parent, state});
  }
}

then there’s the bug again.

Perhaps there’s something in the basic setup, that neutralizes the bug?

Okay, somehow highlightActiveLine() neutralizes the bug

This code doesn’t have the bug:

EditorState.create({
      doc: 'Two',
      extensions: [
        highlightActiveLine(),
        keymap.of([{key: "Enter", run: insertNewlineAndIndent}])
      ]
    });

But when I comment highlightActiveLine(), it does show the bug

EditorState.create({
      doc: 'Two',
      extensions: [
    //    highlightActiveLine(),
        keymap.of([{key: "Enter", run: insertNewlineAndIndent}])
      ]
    });

And highlightActiveLine() is added to basic-setup, so that’s why it works there.

An interesting thing to mention would be what kind of mobile phone / mobile view you’re using.

1 Like

I’m using Samsung Note 10+, with newest Chrome. I hear other users with other phone types experience similar issues.

Also, when I switch off the mobile view, and go with “Computer view” the bug goes away.

My Chrome (97, Linux) doesn’t have Note 10+ in its device list, but when I enable another Samsung phone (Galaxy A15/71) I still don’t see this issue.

The bug is not reproducible on other browser on my Note10+, like Firefox. But there’s the same bug on Edge; which leads me to believe any Chromium Browser would be affected.

@marijn I’m willing to Try and run any POC you’d like and report the output to you, if that’s what it takes.

Cause I have a feeling you find my solution with Text.of unsatisfactory?

@marijn So what’s our plan on this?

I don’t have a plan, and until I can reproduce the issue, it seems hard for me to diagnose what’s going on.

I don’t have a plan, and until I can reproduce the issue, it seems hard for me to diagnose what’s going on.

Well, I’m constantly experiencing the issue, and so do some of my users.

Is there any kind of investigation I can do on my end to provide some necessary details you would need?

Are you sure you’re following the steps?

  1. Start with an empty EditorState (doc: "")
  2. Add some letters, like "One" but without newline at the end
  3. Call insertNewlineAndIndent()

If you call insertNewlineAndIndent() on an empty line or line with spaces, the bug is not reproducible.
And also if you have highlightActiveLine() extension added it won’t be reproducible either. And I also can’t reproduce it on a “Computer version” in my phone, only mobile.

When I do that I see one new "\n" in EditorState, but two new lines in the view.

I am seeing the exact same behaviour in pixel 5 emulator and also on Mac OS Chrome Version 98.0.4758.80: pixel 5 device/ galaxy fold/ or any android device.

If I don’t use highlightActiveLine() extension this happens on every newline, but if I use highlightActiveLine() extension It only happens when there are 2 or more “words” (words = its own span tag)

ezgif-1-2fb7eab5cf

I think similar bugs have been also reported by some other users in the github issues:

1 Like

Here is another similar case, I’m not sure if there is any relationship between these cases.
My device: iPhone 11 with iOS 15.3.1, I just use Safari to open codemirror.net/6 and use iOS default Chinese IME.

If you select the words and immediately press return(换行 at the right corner), two new lines will be created:
image

If you select the words and wait for about 2 seconds then press return, only one new line will be created (which is what I need):
image

I’m not quite good at coding so sorry if causing trouble to you.

1 Like

Thanks for your patience. I’m not sure what I did different compared to the last time I tried to reproduce this (maybe I wasn’t starting with a blank document), but I was able to reproduce this now. This patch should fix it:

I’ve updated the website to use the current code. If you still see issues, please open a github issue with more information.

2 Likes

Thanks for your patience. I’m not sure what I did different compared to the last time I tried to reproduce this (maybe I wasn’t starting with a blank document), but I was able to reproduce this now. This patch should fix it:

I installed 0.19.43, and it works quite well.

@marijn After I installed @codemirror/view@0.19.43 the placeholder extension started to show the placeholder one line too low:

image

PS: Same on 0.19.44.