Skip to content

MD-2768 Cut replaceRange with one callback - #43

Merged
benney merged 4 commits into
mainfrom
feature/md-2768-mos-proxy-cut-replacerange-with-one-callback
Nov 6, 2026
Merged

benney merged 4 commits into
mainfrom
feature/md-2768-mos-proxy-cut-replacerange-with-one-callback

Conversation

@benney

@benney benney commented Nov 5, 2026 •

Copy link
Copy Markdown
Member

Stacked on #42.

When a range's markers are direct children of its container, pass 1 splits the container into keep and cut <mos-range-*> segments and pass 2 drops the cut segment with one callback, instead of one callback per element. Other shapes (nested markers or containers, a marker removed by another component, raw text containers such as textarea) are redone element by element from a buffered copy. A seeded fuzz checks both paths give the same page.

  • CPU per request: 1 MB article 74 → 2 ms, 5 MB 408 → 9 ms
  • A page with a range is buffered, and HTML comments inside the cut are removed
  • RewriterElement.removeAndKeepContent is now required

Minor changeset.

@changeset-bot

changeset-bot Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a64457d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@monetizationos/proxy Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@benney
benney added this pull request to stack #44 November 5, 2026 11:07
@benney
benney force-pushed the feature/md-2768-mos-proxy-cut-replacerange-with-one-callback branch from 3b5e01b to 230bd7f Compare November 5, 2026 11:10
Copilot AI balanced review requested due to automatic review settings November 5, 2026 11:10

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The optimization can produce malformed output through descendant marker matches and missed MathML containers, and can delete or reorder insertions from earlier components.

3 open issues
What changed in this PR

Optimizes surface-component range replacement with a two-pass wrapper approach, building on #42’s element-by-element fixes and retaining that path as a fallback.

Changes:

  • Buffers eligible responses and removes wrapped ranges with one callback.
  • Requires removeAndKeepContent in rewriter adapters.
  • Adds equivalence, fallback, and seeded fuzz tests, plus a minor changeset.
File Description
test/​stages/​wrappedRange.spec.ts Tests wrapper output, fallbacks, component interactions, and fuzz equivalence.
test/​stages/​voidElements.spec.ts Keeps void-element tests on the element-by-element path.
test/​fakes/​LolHtmlRewriter.ts Adds unwrapping support and handles responses without bodies.
test/​fakes/​EndTagSpyRewriter.ts Extracts the reusable end-tag callback spy.
src/​stages/​wrappedRange.ts Plans wrapper segments, fallback checks, and range removal.
src/​stages/​surfaceComponents.ts Coordinates buffering, wrapper passes, and fallback.
src/​adapters/​HtmlRewriterAdapter.ts Requires removeAndKeepContent on rewriter elements.
.changeset/​range-wrapper-cut.md Documents the optimization and adapter contract change.

Review effort: Balanced

Comment thread src/stages/wrappedRange.ts Resolved
Comment thread src/stages/wrappedRange.ts Resolved
Comment thread src/stages/wrappedRange.ts Resolved
@benney
benney force-pushed the feature/md-2768-mos-proxy-cut-replacerange-with-one-callback branch from 230bd7f to 2e2ebb0 Compare November 5, 2026 12:39
@benney
benney force-pushed the feature/md-2768-mos-proxy-cut-replacerange-with-one-callback branch 2 times, most recently from 3de0133 to 0e43518 Compare November 5, 2026 16:34
Base automatically changed from feature/md-3007-mos-proxy-fix-replacerange-edge-cases to main November 6, 2026 09:14
Removing a range element by element costs a callback per element. Pass 1
now splits the container into keep and cut `<mos-range-*>` segments by
inserting tags at the container's edges and next to the markers, and
pass 2 unwraps the keep segments and drops the cut one with a single
callback. The wrapper handlers run ahead of every other component, so
what those insert lands outside the segments.

The split only balances when both markers are direct children of the
container. A nested marker or container, a marker removed by an earlier
component, or a raw text container makes the wrapper report
the page unsupported, and the page is redone element by element from a
buffered copy. A seeded fuzz checks both paths give the same page.

`RewriterElement.removeAndKeepContent` is now required; lol-html and
HTMLRewriter elements already have it, so every adapter gets the cut.

HTML comments inside the cut are now removed with it.
A marker selector with a combinator could match a grandchild through the
direct-child selector, and a container selector list matched more than it
should, so both now go straight to the element path. A component ahead of
the range that inserts on the container, the start marker or inside the cut
now sends the page to the element path, which places those inserts
differently. The fuzz covers inserts from components on both sides of the
range.
@benney
benney force-pushed the feature/md-2768-mos-proxy-cut-replacerange-with-one-callback branch from 0e43518 to 99c5739 Compare November 6, 2026 09:14
@benney
benney merged commit f440059 into main Nov 6, 2026
3 checks passed
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.

3 participants