Skip to content

Commit 29249d0

Browse files
committed
docs(webview): record the narrowed TABLE-DELIM arm and its measurement
Correct the field headers to describe the delta-based TABLE-DELIM arm instead of the old presence-based one: table-skeleton.ts's PERF paragraph now explains that only a delimiter row completing/breaking or a cell-count change takes the full walk, and image-field.ts drops the false 'a table cell' entry from its list of SHAPE-only regressing classes. Repair the two cm-table-skeleton.test.ts comments whose stated reason ('the line carries a |') stopped being true once TABLE-DELIM became a per-line shape delta; the offsets and negative pins they document are unchanged. PERF.md, PERF-log.md, LEARNING.md and TODO.md are updated in the separate local-only .claude/ tree (per this repo's TODO-local-mode convention) and are not part of this commit.
1 parent b9fb7e3 commit 29249d0

3 files changed

Lines changed: 32 additions & 21 deletions

File tree

src/webview/cm/image/image-field.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,16 @@
6262
// which G2 alone cannot see. Rationale + the check itself live in that file, which also
6363
// owns the roster of bounded fields that keep a NARROWER structural predicate of their own
6464
// instead; no copy of that roster is kept here, because a copy goes stale the next time one
65-
// of them moves. ⚠️ PERF: that structural term is PRESENCE-based over the whole changed
66-
// line, so typing in the body of a list item, a blockquote line, a table cell or an ATX
67-
// heading — and every Enter — now takes the full walk this field's bounding exists to
68-
// avoid. THIS field's own full-walk cost was measured at 0.71–0.75 ms/keystroke (19 KB /
69-
// 150 block images and 154 KB / 1200 block images) — essentially flat in document size,
70-
// which the table field's is NOT, so neither field's number may be inferred from the
71-
// other's. Accepted on that measurement, not free: see PERF.md.
65+
// of them moves. ⚠️ PERF: that structural term's SHAPE arm is still PRESENCE-based over
66+
// the whole changed line, so typing in the body of a list item, a blockquote line, or an
67+
// ATX heading — and every Enter — still takes the full walk this field's bounding exists
68+
// to avoid. Its TABLE-DELIM arm is NOT presence-based (a per-line SHAPE-DELTA,
69+
// `tableRowShapeChanged`), so this field no longer full-rebuilds merely because a `|` sits
70+
// somewhere else in the document. THIS field's own full-walk cost was measured at
71+
// 0.71–0.75 ms/keystroke (19 KB / 150 block images and 154 KB / 1200 block images) —
72+
// essentially flat in document size, which the table field's is NOT, so neither field's
73+
// number may be inferred from the other's. Accepted on that measurement, not free: see
74+
// PERF.md.
7275
// A reused widget whose document position SHIFTED is reconstructed with the new
7376
// docFrom (cheap: same alt/safeUrl/slice, NO re-parse). The small pure leaf
7477
// helpers (mergeIntervals / lineExpandWithNeighbours / intersects /

src/webview/cm/table/table-skeleton.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,16 @@
2424
// which ORs G2 (an incomplete post-edit frontier → full walk; the later
2525
// background-parse publication, a `!docChanged` tree-identity change, full-walks
2626
// again to self-heal) with G-STRUCT (a structural reparse re-shapes boundaries
27-
// outside the span with a complete frontier → full walk). ⚠️ PERF: G-STRUCT is
28-
// PRESENCE-based over the whole changed line, and a table cell's line always
29-
// carries a `|`, so typing INSIDE a cell takes the full walk — exactly the
30-
// whole-tree materialisation + per-table `parseTable` this field exists to skip.
31-
// Measured and accepted, not free: see PERF.md. Soundness (bounded ≡ fullWalk,
32-
// ranges AND parses) is pinned by cm-table-skeleton.test.ts.
27+
// outside the span with a complete frontier → full walk). ⚠️ PERF: G-STRUCT's
28+
// TABLE-DELIM arm is a per-line SHAPE-DELTA (`tableRowShapeChanged`), not a
29+
// presence test over the whole changed line, so typing INSIDE a cell whose row
30+
// shape is unchanged stays on the bounded path this field exists to protect —
31+
// only a delimiter row completing/breaking or a header's cell count changing
32+
// takes the full walk. G-STRUCT's OTHER arm (SHAPE) is still presence-based, so
33+
// a list-item body, a blockquote line, an ATX heading, or any Enter still takes
34+
// the full walk regardless of this field. Measured and accepted, not free: see
35+
// PERF.md. Soundness (bounded ≡ fullWalk, ranges AND parses) is pinned by
36+
// cm-table-skeleton.test.ts.
3337

3438
import { syntaxTree } from "@codemirror/language";
3539
import { type EditorState, StateField, type Transaction } from "@codemirror/state";

test/webview/table/cm-table-skeleton.test.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,14 @@ describe("tableSkeletonField bounded ≡ fullWalk", () => {
163163
mount: (parent) =>
164164
settledMount({ state: EditorState.create({ doc, extensions: exts() }), parent }, 10_000),
165165
observe: (view, requireUnstarvedFrontier) => {
166-
// Offset chosen to land INSIDE the `prose` paragraph. The offset is load-bearing:
167-
// an edit on either table's own lines carries a `|`, which trips the structural
168-
// guard's TABLE-DELIM arm and routes the dispatch to the FULL walk — leaving this
169-
// test comparing full against full and unable to see a broken boundedUpdate. The
170-
// negative pin below is what keeps that from drifting back silently.
166+
// Offset chosen to land INSIDE the `prose` paragraph, i.e. OUTSIDE both tables'
167+
// node ranges. That is what keeps this test on the REUSE half of `boundedUpdate`
168+
// (the sibling below puts the edit's span ON a table to exercise the RE-WALK half
169+
// instead) — it is no longer about pipe presence: the narrowed TABLE-DELIM arm is
170+
// a per-line SHAPE delta (`tableRowShapeChanged`), not "any `|` on the line", so an
171+
// in-cell keystroke that leaves a row's shape unchanged stays on the bounded arm
172+
// too. The negative pin below still guards against a regression that would route
173+
// this specific edit to the FULL walk.
171174
const proseAt = doc.indexOf("prose") + 2;
172175
const tr = view.state.update({ changes: { from: proseAt, insert: "x" } });
173176
expect(touchesStructuralReparse(tr)).toBe(false); // this edit really is on the bounded arm
@@ -204,9 +207,10 @@ describe("tableSkeletonField bounded ≡ fullWalk", () => {
204207
mount: (parent) =>
205208
settledMount({ state: EditorState.create({ doc, extensions: exts() }), parent }, 10_000),
206209
observe: (view, requireUnstarvedFrontier) => {
207-
// End of `intro` — prose, so the changed line carries no `|` and no structural
208-
// shape. The negative pin keeps that from drifting into the FULL arm, where this
209-
// would compare a full walk against a full walk.
210+
// End of `intro` — prose, with no table-shape signal (no `|`, no delimiter row, no
211+
// cell-count change) for the narrowed TABLE-DELIM arm to fire on, and no other
212+
// structural shape either. The negative pin keeps that from drifting into the FULL
213+
// arm, where this would compare a full walk against a full walk.
210214
const tr = view.state.update({ changes: { from: 5, insert: "X" } });
211215
expect(touchesStructuralReparse(tr)).toBe(false);
212216
view.dispatch(tr);

0 commit comments

Comments
 (0)