Skip to content

fix(engine): fast capture works on Chrome 157+, which wants content=drawable - #7626

Merged
miguel-heygen merged 1 commit into
mainfrom
fix/html-in-canvas-form
Nov 12, 2026
Merged

miguel-heygen merged 1 commit into
mainfrom
fix/html-in-canvas-form

Conversation

@miguel-heygen

Copy link
Copy Markdown
Collaborator

What

Fast (drawElement) capture now marks its canvas the way the running Chrome asks for: layoutsubtree on Chrome up to 156, content="drawable" plus drawable on the composition root on 157+. The single-worker pin for html-in-canvas compositions also recognises the 157 canvas.

Why

Chrome 157 became Stable and renamed the opt-in. The engine's wrapper canvas always set layoutsubtree, so on a 157 browser every fast-capture export died at the first frame with InvalidStateError: Failed to execute 'drawElementImage' on 'CanvasRenderingContext2D': DrawElementImage requires the canvas to have the content=drawable attribute.

fails without the fix: drawElementCanvasForm.browser.test.ts (both cases, against a real Chrome 157.0.8103.78 and against Chrome 152 with its 157 marks simulated) and the new htmlCompiler.test.ts case.

Related work

packages/core/src/htmlInCanvas.ts already owns the form decision for authored canvases (htmlInCanvasForm); the engine was the one capture path still hardcoding the old form. No open PR touches this.

How

  • injectDrawElementCanvas asks the page for htmlInCanvasForm() (the same function core uses) and applies the matching marks. A build with drawElementImage but no requestPaint keeps layoutsubtree, as before.
  • detectRenderModeHints uses core's CAPTURE_CANVAS_SELECTOR instead of its own canvas[layoutsubtree], so a composition authored with the 157 canvas is still pinned to one worker.

Test plan

  • Unit tests added/updated
  • Manual testing performed
  • Documentation updated (if applicable)
  • Comments follow CONTRIBUTING.md "Comments"

What I measured

On a Linux box, headless shell, --enable-features=CanvasDrawElement:

  • Chrome 157.0.8103.78: layoutSubtree is absent from the canvas, updateElementGeometry present; a layoutsubtree canvas throws the error above; content="drawable" plus drawable on the child is accepted.
  • Chrome 152.0.7977.30 (the pinned build): layoutsubtree accepted, content="drawable" refused.
  • New browser test, 3 runs in a row on each of 152 and 157: 2 passed, 0 skipped, exit 0. With drawElementService.ts reverted to main: 152 run 1 failed / 1 passed, 157 run 2 failed.
  • drawElementService.test.ts: 22 passed. htmlCompiler.test.ts: 179 passed; with htmlCompiler.ts reverted, the new case fails (178 pass, 1 fail).

What I did NOT execute

  • A full export on Chrome 157 or on Windows: only the canvas injection and the draw call were exercised.
  • The full engine and producer suites (CI runs them).
  • packages/shader-transitions still probes for layoutSubtree, so on 157 its page-side compositor and html-in-canvas scene capture report unsupported and use their existing fallbacks; unchanged here.

Size

About 120 changed lines, of which about 90 are the new browser test; the fix itself is about 15 lines in two files.

@github-actions

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 267 (base branch 267), smooth 88 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (8)

Unstable (1)

  • seqplainkeys-none-px-r0-root-z100: tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo false, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Verdict: APPROVE · 0 blocker · 0 important · 0 nits · head f45ddb97

The fix uses core's htmlInCanvasForm/CAPTURE_CANVAS_SELECTOR, so the engine and producer now follow the same Chrome-version decision as authored canvases.

Scope

Read the full diff. Rule-2 sweep: every engine drawElementImage call draws root inside __hf_de_canvas, which injectDrawElementCanvas marks. The remaining engine layoutsubtree mentions (frameCapture.ts:1296, threeDProjection.ts:9) are comments. shader-transitions still probes layoutSubtree; the PR discloses this and it uses the existing fallback. The "fails without the fix:" line names drawElementCanvasForm.browser.test.ts and the new htmlCompiler.test.ts case. CI ran the browser test (2 passed; flake gate 10/10). All Actions runs pass at this head, including Windows render verification. Not exercised by anyone: a full export on a real Chrome 157.

@miguel-heygen
miguel-heygen added this pull request to the merge queue Nov 12, 2026
Merged via the queue into main with commit 9c3258c Nov 12, 2026
91 checks passed
@miguel-heygen
miguel-heygen deleted the fix/html-in-canvas-form branch November 12, 2026 23:20
@miguel-heygen miguel-heygen mentioned this pull request Nov 13, 2026
3 of 5 tasks
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.

1 participant