Skip to content

feat(canvas): getContext works without waiting for ready - #158

Merged
triniwiz merged 10 commits into
v3-v8from
feat/no-ready-event
Sep 28, 2026
Merged

triniwiz merged 10 commits into
v3-v8from
feat/no-ready-event

Conversation

@triniwiz

Copy link
Copy Markdown
Member

On the web a <canvas> can be used as soon as it exists. Here, apps had to wait for the Canvas ready event before calling getContext. On Android, a context created before the view had a surface was never attached to it. This PR makes the canvas usable immediately and deprecates ready.

Android

  • Every new surface attaches the view's context: the first one, a recreated TextureView/SurfaceView surface, or one arriving after getContext. Previously the first surface only fired contextReady, and a recreated TextureView surface was ignored. GLView also drops its reference to a released Surface.
  • A frame drawn before the surface existed is shown once the surface attaches, so drawing once in loaded works:
    • 2D carries its pixels across the EGL surface switch (when the size is unchanged; a resize clears, as on the web);
    • WebGL blits the pbuffer frame through a renderbuffer;
    • WebGPU copies the last offscreen frame into the first swapchain texture.
  • WebGPU contexts can be created before there is a window. CanvasGPUCanvasContext.surface is now optional: None means frames render offscreen, both before the view has a window and after it lets go of one. This replaces the surface_lost flag from fix(canvas): keep JS contexts safe after their canvas releases the native context #156, and a detach now drops the wgpu surface instead of keeping a dead one.

JS

  • ready still fires, but is @deprecated. Listening for it, including ready="…" in XML, warns once.
  • Dom no longer waits for ready.
  • The demos start from loaded. The canvas-svg demo waits for its first layout, since it reads clientWidth.

Windows

  • The x64 and arm64 canvasnative.node are rebuilt from this branch.

Testing

  • New lifecycle spec tests, which call getContext the instant a canvas is added to the page:
    • 2D pixels survive the attach;
    • WebGL/WebGL2/WebGPU draw immediately and after frames;
    • on Android, a WebGL/WebGPU frame drawn before the surface is displayed afterwards (checked via the view snapshot).
  • Windows: full canvas-spec 347/349. The two failures are webgpu.video and also fail on v3-v8. lifecycle passes 10/10.
  • Android and iOS: not built yet (the Android build needs a macOS host). Run canvas-spec with --suite lifecycle and a demo such as canvas-three.
  • WebGL's carry-over needs an ES 3 context (glBlitFramebuffer). Android drivers return one for WebGL 1's 2.0 request; on a true ES 2-only context the carry-over is skipped.

A context made before the Android view had a surface stayed offscreen:
the first surface only fired contextReady, and a recreated TextureView
surface was ignored. Every new surface now attaches the context
(resize()), carrying 2D pixels over when the size is unchanged.

WebGPU contexts can be created before there is a window: the context's
wgpu surface is optional, None until the view has one and again once it
lets go of it, with frames rendering offscreen meanwhile.
getContext works as soon as the canvas exists, as on the web. The event still fires; listening for it warns once.
…existed

A frame drawn before the view had a surface went to the pbuffer
(WebGL) or the offscreen texture (WebGPU) and was dropped when the
window surface attached, so a canvas drawn once in `loaded` stayed
blank. The attach now carries that frame over and presents it:
WebGL blits it through a renderbuffer across the EGL surface switch,
WebGPU copies it into the first swapchain texture.
@coderabbitai

coderabbitai Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: e6291df2-ecc7-4d48-b5cd-641ba701fd74

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

nativeDetach2DSurface passed 12 of ContextAttributes::new's 13 arguments,
so canvas-android did not compile.
Layout resized the pbuffer to the size it already had before the surface
appeared, which recreated it blank and lost the frame the surface was
meant to show.
GrDirectContext deletes its GL names on whichever context is current. When
another canvas was current, collecting a 2d context deleted that canvas's
objects and its later draws did nothing.
NAPI_HOST cannot be folded at build time, so its __non_webpack_require__
survived into the iOS bundle and imported node:module, which the iOS runtime
does not have. The app failed to start.
@triniwiz
triniwiz merged commit e49ed0a into v3-v8 Sep 28, 2026
10 of 17 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.

1 participant