Repository navigation
feat(rust): update cycle, node methods, commands, transforms and listeners - #119
Merged
Merged
Conversation
…eners The first part of M1 (rust/DESIGN.md): the core model can now be edited, not only parsed and written. - The update cycle, ported line by line from LexicalUpdates.ts: editor.update (discrete or committed at the next read), nested and queued updates, tags, normalization of adjacent simple text (LexicalNormalization.ts), node transforms (leaves first, the root last), garbage collection of detached nodes (LexicalGC.ts), the selection check, discarding a failed update, and the text content and update listeners. Commands: createCommand, registerCommand with the five priorities, dispatchCommand. setEditorState, which marks a parsed state's nodes dirty so normalization and transforms run on it. - getWritable marks nodes dirty in JS's order (the order update listeners see), with Rc uniqueness standing in for _cloneNotNeeded; the dirty sets are insertion-ordered like JS's Map and Set. - Node methods with UTF-16 offsets: remove, replace, insertBefore, insertAfter, select*, splice (with selection repair), append, clear, the element setters, splitText, mergeWithSibling, spliceText, setTextContent and the text setters and toggles, with TabNode's and RootNode's overrides. The selection model and the helpers node methods use to keep it valid (LexicalSelection.ts); selection editing and carets come next. - lexical-conformance replays scripts/* with an interpreter of ops.ts's script language. A script that needs selection editing or carets is counted as waiting on them, never as passing. Checked in rust/: cargo fmt --check, clippy -D warnings, cargo test (including new tests that doctored script vectors fail), rustdoc -D warnings, cargo +1.88 check. Conformance: scripts/updates 12/12, scripts/commands 3/3, scripts/listeners 2/2 and scripts/transforms 4/4 of the cases without typing, scripts/selection 2/2 without selection editing; meta, serialization/core and property/documents unchanged; 0 failures. setEditorState was also checked against the JS package on a document with mergeable, empty and formatted text, with and without a transform, and on an empty state: identical listener calls, transform calls, errors and JSON. Amp-Thread-ID: https://ampcode.com/threads/T-16d45229-bfa8-417a-a091-d3e3888d830d
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #117 (
rust-core); review that one first. This is the first part of M1 inrust/DESIGN.md: the Rust port can now be edited, not only parsed and written.What changes
LexicalUpdates.ts,LexicalNormalization.tsandLexicalGC.ts:editor.update, with nested and queued updates and tags;createCommand,registerCommandwith the five priorities,dispatchCommand;setEditorState, which marks a parsed state's nodes dirty so normalization and transforms run on it.getWritablemarks nodes dirty in JS's order, which is the order update listeners see. TheRc's uniqueness stands in for_cloneNotNeeded, and the dirty sets are insertion-ordered like JS'sMapandSet.remove,replace,insertBefore/insertAfter,select*,splice(with selection repair),append,clear, the element setters,splitText,mergeWithSibling,spliceText,setTextContentand the text setters and toggles, plus the TabNode and RootNode overrides. Also the selection model, and the helpers node methods use to keep it valid.ops.ts's script language replaysscripts/*. A script that needs selection editing or carets is counted as waiting on them, never as passing.A headless editor has no event loop, so a non-discrete update commits at the next
reador discrete update rather than in a microtask (DESIGN.md).How it was checked
In
rust/:cargo fmt --check, clippy-D warnings,cargo test(including a new test that doctored script vectors fail), rustdoc-D warnings,cargo +1.88 check.scripts/updatesscripts/commandsscripts/listenersscripts/transformsscripts/selectionscripts/caretmeta,serialization/coreandproperty/documentsare unchanged.I also changed eight fields across the script vectors (state, compact JSON, selection, error flag,
splitTextkeys, dirty flags, tags, handler order); each change made its case fail.setEditorStatewas run against the JS package on a document with mergeable, empty and formatted text, with and without a transform, and on an empty state. Listener calls, transform calls, errors and JSON were identical.No changeset:
rust/is not published.