Skip to content

Split equal-sibling buckets by shape once comparisons keep failing - #191

Merged
joeldrapper merged 2 commits into
mainfrom
claude/project-thread-7y3nfe-equal-buckets
Oct 8, 2026
Merged

joeldrapper merged 2 commits into
mainfrom
claude/project-thread-7y3nfe-equal-buckets

Conversation

@joeldrapper

Copy link
Copy Markdown
Collaborator

Requested by Joel · project thread

Before: when 1000 empty icons all changed their attributes, the morph took 128ms. The isEqualNode pass groups candidates by text content, so siblings with the same text but different markup were all compared pair by pair. Lists of identical items also rescanned the already-taken candidates for every target.

After: the icon case takes 19ms. 1000 identical items under a changed parent and 1000 icons with one changed are both about 40% faster. Plain lists stay within noise (up to 3%, with one 9% reading on a 3ms case).

The matching result doesn't change. Equal nodes always have the same shape, so splitting a bucket by shape keeps every candidate a target could equal, in the same order.

How: candidates are still grouped by text. Once the failed comparisons in a group outnumber its candidates, EqualBuckets splits that group by shape, using the shapes the sibling list already caches. A group of more than one candidate also skips the candidates already taken at its start. The identical-sibling ordering uses the same buckets.

Tests: test/new/equal-buckets.browser.test.ts passes on both main and this branch. Coverage is 100%.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VJNvudrTrB2rfJaLWKRMsc


Generated by Claude Code

The isEqualNode pass bucketed candidates by text content, so siblings with
the same text but different markup, like 1000 empty icons whose attributes
all change, were compared pair by pair (128ms). Once the failed comparisons
in a bucket outnumber its candidates, the bucket is now split by shape, and
equal nodes always share a shape, so a target only looks at candidates it
could equal, in the same order. A bucket of many also skips its taken
prefix, so identical siblings aren't scanned again for each target.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VJNvudrTrB2rfJaLWKRMsc
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-07T16:43:13.719161Z 5da1da2 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Copy link
Copy Markdown
Collaborator Author

The Fuzz jobs fail in all three browsers on the same form-state seed, 37653248352 (preserveChanges, root #w2). Two name="t" textareas, one with form="missing", become one textarea with form="missing" class="x". The user's typed text in the second textarea is lost.

This failure isn't from this PR. The seed fails the same way on current main (2e4a5d1) in Chromium locally:

VITE_MORPHLEX_FUZZ_FORM_SEEDS=1 VITE_MORPHLEX_FUZZ_FORM_SEED_START=37653248352 vitest run test/new/form-state-fuzz.browser.test.ts

There's no fix for it yet, so I haven't ported one. I haven't re-run the jobs either, because the seeds come from the run id and a re-run would hit the same seed. I'm raising the main bug in the project.


Generated by Claude Code

With preserveChanges, a typed textarea with default text and an untouched
one of the same name lost the typed one when the target had a single
textarea: its default text gave it another outline than the target's, so
it couldn't take the target ahead of the untouched one. A textarea's text
is only its default value, so the outline now leaves it out.

Found by the form-state fuzzer (seed 37653248352).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VJNvudrTrB2rfJaLWKRMsc
(cherry picked from commit 95ca297)

Copy link
Copy Markdown
Collaborator Author

I ported the fix from #192 into this branch (5da1da2) so the Fuzz jobs can go green. That commit is a no-op here once #192 merges.


Generated by Claude Code

@joeldrapper
joeldrapper merged commit a175a13 into main Oct 8, 2026
7 checks passed
@joeldrapper
joeldrapper deleted the claude/project-thread-7y3nfe-equal-buckets branch October 8, 2026 07:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants