Skip to content

Fix Canvas image reload and cancellation lifetimes - #1893

Merged
bkaradzic-microsoft merged 4 commits into
BabylonJS:masterfrom
bkaradzic-microsoft:pr/canvas-image-reload
Oct 2, 2026
Merged

bkaradzic-microsoft merged 4 commits into
BabylonJS:masterfrom
bkaradzic-microsoft:pr/canvas-image-reload

Conversation

@bkaradzic-microsoft

Copy link
Copy Markdown
Member

Summary

  • Give every Canvas Image.src assignment its own cancellation lifetime and reflect the assigned source immediately.
  • Ignore cancelled URL/data-URL completions instead of reporting errors or replacing a newer image.
  • Separate decoded-image release from load cancellation. URL completion must not call Dispose() and poison subsequent loads; data-URL replacements must release the previous image.
  • Add eight local-file/data-URL regressions, including repeated loads, superseded requests, and recovery after a missing-file error.

Independence

Based directly on upstream master at 2a9dc944, with published Babylon.js 9.21.2 and unchanged native dependency pins. Not stacked on the other new PRs.

This extracts only the image-lifecycle portion of the shotgun work. It does not add SVG support, Canvas branding changes, or a silent-error policy. It retains the PNG normalization from #1887. It does not replace #1882's separate image-parser error handling; the changes should compose.

Validation

  • Windows x64 / D3D11 / Chakra / Release JavaScript unit suite: 94 passing, 29 existing optional cases pending.
  • The same tests with upstream Image.cpp/Image.h produce six failures, including the two URL reload timeouts; restoring this fix passes all eight new cases.
  • The new PNG fixture is an authored 2x1 red/blue image; no network service, rendering reference, tolerance, or catalog changes are needed.

Copilot AI lite review requested due to automatic review settings September 18, 2026 22:28

Copilot AI 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.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

Review effort: Lite
Findings: 1 High severity · 1 Medium severity

Open (2)
What changed in this PR

Fixes Canvas Image.src lifecycle so each assignment has an independent cancellation scope, cancelled completions don’t surface as errors or override newer loads, and decoded-image cleanup is separated from load cancellation.

Changes:

  • Split image release from cancellation (ReleaseImage() vs Dispose()), and release previous decoded images on replacement.
  • Reset cancellation lifetime per src assignment and ignore cancelled URL/data-URL completions.
  • Add JS unit tests + fixture asset to cover reloads, superseded requests, and recovery after errors.
File Description
Polyfills/​Canvas/​Source/​Image.h Adds ReleaseImage() API for separating decoded-image cleanup from cancellation/disposal.
Polyfills/​Canvas/​Source/​Image.cpp Refactors image cleanup and per-src cancellation; ignores cancelled completions and avoids poisoning future loads.
Apps/​UnitTests/​JavaScript/​src/​tests.javaScript.all.ts Adds regression tests for repeated loads, superseding, immediate src reflection, and recovery after missing-file errors.
Apps/​UnitTests/​JavaScript/​dist/​tests.javaScript.all.js Compiled test output reflecting the new regression suite.
Apps/​UnitTests/​CMakeLists.txt Packages new PNG fixture used by the added tests.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread Polyfills/Canvas/Source/Image.cpp
Comment thread Apps/UnitTests/JavaScript/src/tests.javaScript.all.ts Outdated
@bkaradzic-microsoft

Copy link
Copy Markdown
Member Author

Fixed the Windows SDK installation failure in 772c425.

Install/Test reuses Tests.JavaScript.cpp, but the test-only UrlLib resolver introduced a dependency on headers that are not part of the installed SDK. Its headers, resolver registration/cleanup, and direct linkage now follow the existing native image-test feature flag. No private headers were added to the SDK, and no production Image behavior changed.

Validation: the real installed-SDK consumer builds without UrlLib/UrlLib.h; the internal JavaScript suite still reports 94 passing / 29 pending, including both deterministic supersession cases. Fresh CI will run on this commit; there is no reason to retry the superseded failing job.

A verified Balanced Copilot re-review is still pending: the public review-request API ignores the effort field, so I have not substituted another Lite request.

bkaradzic-microsoft added a commit to bkaradzic-microsoft/BabylonNative that referenced this pull request Sep 30, 2026
Review-Group: E3
Source: PR BabylonJS#1893
Squashed final review changes, including regressions and review follow-ups.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 60c2ec68-6de1-445d-9fc9-b699db737eae

@bghgary bghgary 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.

[Reviewed by Copilot on behalf of @bghgary]

Concerns inline.

Comment thread Polyfills/Canvas/Source/Image.cpp
bkaradzic-microsoft and others added 4 commits October 1, 2026 16:53
Use a fresh cancellation source for each src assignment, ignore superseded
completions, and release replaced image data without cancelling the load.
Preserve image error reporting and PNG normalization; add local reload,
cancellation, src reflection, and error-recovery regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 60c2ec68-6de1-445d-9fc9-b699db737eae
Use an in-memory URL resolver and a final queued image completion as the
barrier for cancellation assertions, instead of sleeping for 50 ms.
Keep real app URL reload/error coverage and document JS-thread serialization
of data decoding and src/disposal.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 60c2ec68-6de1-445d-9fc9-b699db737eae
Guard the test-only UrlLib resolver with the existing native image-test
feature flag, including its headers, cleanup, registration, and linkage.
The installed SDK consumer reuses this source without image tests and
must not depend on private UrlLib headers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 60c2ec68-6de1-445d-9fc9-b699db737eae
SetBuffer replaces the decoded pixels, but contexts cached a NanoVG texture by NativeCanvasImage pointer. Compare a content generation and keep the old handle until flush. Cover URL-to-URL and URL-to-data reloads, and stop the reload tests from referencing a webpack helper that is not in scope.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e6c3c123-c355-4790-a3d4-94337ed6e052
@bkaradzic-microsoft
bkaradzic-microsoft enabled auto-merge (squash) October 2, 2026 01:07
@bkaradzic-microsoft
bkaradzic-microsoft merged commit 24823c1 into BabylonJS:master Oct 2, 2026
35 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