kokhlo commented on issue #44371:
URL: https://github.com/apache/superset/issues/44371#issuecomment-5709694881

   I dug into this on current master — the mechanism survives the react-ace 10 
→ 15 upgrade, in a slightly different flavor.
   
   What happens on master (SQL Lab path):
   
   - `EditorWrapper` renders a fully controlled editor: `value={sql}` + 
`onChange` (`src/SqlLab/components/EditorWrapper/index.tsx`), backed by 
`EditorHost` → `AceEditorProvider` → react-ace 
(`src/core/editors/AceEditorProvider.tsx`).
   - With N cursors, Ace applies a keystroke per selection 
(`forEachSelection`), so the session `change` event fires N times with N 
intermediate document values, and only the last one is the final text. Every 
firing goes straight through `onChange` → `setSql` + redux dispatch.
   - Whenever React renders with an intermediate value while the editor already 
holds the final one, react-ace's `componentDidUpdate` sees `getValue() !== 
props.value` and calls `editor.setValue(...)` mid-keystroke. That is the 
`setValue(intermediateText, 1)` + `navigateFileEnd()` pair from your trace. On 
master (react-ace 15) there is a save/restore around it, but it uses 
`selection.toJSON()/fromJSON()`, which is a single-range API — a 
multi-selection collapses to its first range. Either way the extra cursors are 
destroyed mid-keystroke, and subsequent characters land wherever the surviving 
cursor points (document end in your 6.0.0 trace).
   
   Fix plan, in `AceEditorProvider` so every editor surface benefits: coalesce 
change emissions per keystroke — buffer the latest editor value and call the 
consumer `onChange` once per microtask batch. Intermediate per-selection values 
then never reach the controlled `value` prop, `getValue() === props.value` 
holds at every render, and react-ace's out-of-band `setValue` never fires while 
typing. Programmatic value changes (format SQL etc.) keep the existing 
single-range restore path, which is correct for single-cursor restores.
   
   Regression test: simulate multi-cursor typing by firing `onChange` twice 
synchronously (intermediate value, then final) and assert the provider emits 
exactly once with the final value — that assertion fails on current master.
   
   PR within the hour.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to