Skip to content

test(render): guard page creation after native rejection - #2001

Merged
schlessera merged 1 commit into
mainfrom
test/1978-native-boundary-be80cc0a
Oct 16, 2026
Merged

schlessera merged 1 commit into
mainfrom
test/1978-native-boundary-be80cc0a

Conversation

@schlessera

@schlessera schlessera commented Oct 16, 2026 •

Copy link
Copy Markdown
Owner

Closes #1978

What changed

Adds real-Chrome regression coverage for a rejection assertion that succeeds before the following page fails with Target.createTarget: Target closed. Four ordinary native replies remain pending while the shared rejection helper runs. The test checks subsequent page creation, every pending reply and continued connectivity across 30 bounded batches.

Why this shape

The explicit-await correction already shipped in #2000. This test guards the additional connection-close failure, which the existing large-response test did not exercise. Replacing only the shared helper with the original synchronous .rejects.toThrow reproduces the exact exception without instrumentation. No product code, browser transport, deadlines, isolation arguments or original PDF assertions change; no consumer-visible changeset is needed.

A separate bounded control uses the original predecessor/final PDF inputs and the real renderer (byte-identical to the original failed source). The old matcher causes socket close 1002 / unsupported control frame during the following renderer.ts:324 page creation, before shutdown, while the recorded Chrome root is still running. The unchanged explicit-await helper passes all 30 renderer pairs. The original historical job lacks socket telemetry, so its exact receive-byte grouping/scheduler interval cannot be reconstructed; the controlled cause is established without claiming those absent historical facts.

Proof

Behavioral receipts use head cb7e38721de83bdd6cdcc9e4c69f9845eeea10c4 / base 45908608df63b07ee3d10d84ac608d132aa21caa. Refreshed candidate 740679278c9a103e71e112c225e4781ce88b022c is based on 9bebef7bfed47139792ccaf1d22d4ac7f5f093e9; the renderer, shared helper and regression are unchanged. Bun 1.4.2+744846f84, Puppeteer 25.12.0, branded Google Chrome 155.0.8059.39.

  • Failing mutation: restore expectAsyncRejection to await expect(operation).rejects.toThrow(message) and run bun run test tests/export-native-rejection-runtime.test.ts -t 'pending native replies'. 0 pass / 1 fail / 88 assertions, exact TargetCloseError: Protocol error (Target.createTarget): Target closed at the following page; no observer or protocol patch. Mutation restored.
  • Restored BRAIN_REQUIRE_CHROME=1 bun run test tests/export-links-runtime.test.ts tests/export-native-rejection-runtime.test.ts: 23 pass / 292 assertions. All original 21 PDF cases remain; the reported final case passes in 75.33 ms.
  • Real-renderer diagnostic comparison: original matcher fails at the 15th pair with the same exception, close 1002 and a live Chrome root before cleanup. Explicit await passes 30 pairs / 150 assertions / 4,020 valid CDP messages, then normal shutdown and exit 0. Ordinary browser commands only; no sleeps, altered frames, forced signals or widened deadlines.
  • bun run check:pr --base origin/main: 852 pass / 5,459 assertions, all local preflight gates pass.
  • Refreshed bun run check:pr --base origin/main also passes 852 cases / 5,459 assertions.
  • Initial hosted run 38827216679, attempt 1, completed with 12 successful jobs, failed unit (4) and failed aggregate. All 14 actual checkout logs match 5d65d2c14725c57164e41ec37e595c271f8fe662, parents 45908608df63b07ee3d10d84ac608d132aa21caa / cb7e38721de83bdd6cdcc9e4c69f9845eeea10c4, tree 3bbe7caf26b0edf23b7863dcb8c23bc406b095de (API/Git verified). The new regression passes in 1183.03 ms; the original final PDF case passes in 94.65 ms. Sole failing test is the existing MAINTENANCE_CHILD_GONE_BEFORE_TRANSPORT assertion at packages/ui-server/tests/sync-mirror.test.ts:200, corrected by main's test(ui-server): distinguish teardown writes from live descendants #1962 / 9bebef7bf. The full failed run completed before this refresh; it was not rerun unchanged or cancelled for a push.
  • Fresh selected run 38829751515, attempt 1, passes all 14 CI jobs and aggregate, with no retained/skipped proof. All 14 actual checkout logs match 9721cbe1f37d87cccfc7b69cc0a1baa7415ad6d5, parents 9bebef7bfed47139792ccaf1d22d4ac7f5f093e9 / 740679278c9a103e71e112c225e4781ce88b022c, tree 7611912f25a00feab48ed09f9b7fbc80ed564419 (immutable API/Git verified). The new regression passes in 1773.99 ms; the original final PDF case passes in 130.90 ms. Both corrected sync-mirror cases pass. Contract and project-sync gates also pass.
Selected job Verified job ID
changeset 116745550554
verify 116745709622
layout (1) 116745709632
browser (1) 116745709637
pack 116745709642
runtime 116745709654
unit (4) 116745709661
browser (2) 116745709673
unit (1) 116745709676
captures 116745709725
layout (2) 116745709741
unit (3) 116745709751
unit (2) 116745709765
proof 116753034084

Checklist

  • Focused local preflight/behavioral receipts and complete selected hosted proof passed; actual head/base/job checkout evidence is in Proof.
  • Acceptance criteria from the issue are all met, or the gap is named below.
  • The PR and completed/advanced issues have verified release milestones under docs/process/github.md.
  • A changeset is included, or this changes nothing a consumer can see.
  • No personal data anywhere in the diff — the leakage gate covers the whole tree.
  • The integration contract index or relevant component is updated in this same commit, or nothing in the machine surface moved.
  • Docs under docs/ reflect the change, or nothing documented moved.

Anything left open

Nothing remains before the normal merge/reconciliation step. Historical unretained byte grouping/scheduling remains unknown; it is not needed to assert the observed causal control or to preserve the existing correction. No additional renderer behavior change is selected.

@schlessera schlessera added this to the 0.44.0 milestone Oct 16, 2026
@schlessera schlessera added type: test Coverage, harness or proof work with no behaviour change. area: render render-template and the network-denied puppeteer renderer. area: ci CI workflows, the gates they run, release scripts, packaging. labels Oct 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ci CI workflows, the gates they run, release scripts, packaging. area: render render-template and the network-denied puppeteer renderer. type: test Coverage, harness or proof work with no behaviour change.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

render: hosted PDF disclosure proof fails with Target.createTarget closed

1 participant