fix(frontend): take the editor's post-edit content, not setCode's argument (#10562)

#10560 changed the script editor's change handler to read `e.detail` instead of
`editorCode`, on the reasoning that the two only diverge while the editor is
being torn down. They also diverge in a live editor: `setCode` dispatches the
string it was handed, but `alignCodeWithEditor` applies that string to Monaco
first, and the resulting `onDidChangeModelContent` runs `updateCode`
re-entrantly — so if the model normalized the text (EOL is the reachable case;
`ScriptBuilder` builds template content with a `\r\n` join), `editorCode`
already holds the buffer's version and the payload is the pre-normalization
one. Taking the payload leaves `code` disagreeing with what the editor shows,
which the external-write effect then tries to reconcile on every change.

The language-switch fix in that PR is `alignCodeWithEditor` clearing the timer
its own write armed; that part stands and is unaffected. This restores the
handler to the buffer-true read.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ruben Fiszel
2026-08-06 09:59:19 +02:00
committed by GitHub
co-authored by Claude Opus 5
parent 74737d16dd
commit 1846bd5ce5
@@ -2762,11 +2762,12 @@
awareness={wsProvider?.awareness}
on:change={(e) => {
if (activeModuleTab === null) {
// The payload, not `editorCode`: the editor also fires this while it is
// being torn down (the unmount flush), and a destroyed component's
// `bind:` writes no longer reach us — re-reading would take the value
// from before the change and write it back over `code`.
code = e.detail
// `editorCode`, not the payload: `setCode` dispatches the string it was
// handed, but Monaco may have normalized it (EOL) while applying it, and
// the re-entrant `updateCode` that runs inside `setCode` has already put
// that normalized text here. Taking the payload would leave `code`
// disagreeing with the buffer.
code = editorCode
lastSyncedCode = code
inferSchema(e.detail)
} else {