Skip to content

Add DOM globals polyfill + native AbortController for Playground#1708

Open
bkaradzic-microsoft wants to merge 3 commits into
BabylonJS:masterfrom
bkaradzic-microsoft:weekend/tpc-1579-dom-globals
Open

Add DOM globals polyfill + native AbortController for Playground#1708
bkaradzic-microsoft wants to merge 3 commits into
BabylonJS:masterfrom
bkaradzic-microsoft:weekend/tpc-1579-dom-globals

Conversation

@bkaradzic-microsoft
Copy link
Copy Markdown
Contributor

@bkaradzic-microsoft bkaradzic-microsoft commented May 18, 2026

Wires up native AbortController and adds JS polyfills for TextEncoder + PointerEvent so playgrounds depending on DOM globals stop ReferenceError'ing.

Changes:

  • New Apps/Playground/Scripts/dom_polyfill.js - self-detecting TextEncoder + PointerEvent polyfills.
  • Apps/Playground/Shared/AppContext.cpp - calls Babylon::Polyfills::AbortController::Initialize(env); loads dom_polyfill.js after file_polyfill.js.
  • Apps/Playground/CMakeLists.txt - adds dom_polyfill.js to SCRIPTS list; links AbortController plugin.
  • Apps/Playground/Android/BabylonNative/CMakeLists.txt - adds PRIVATE AbortController to BabylonNativeJNI link list (without this, Android builds fail with missing header - verified via CI).
  • Apps/Playground/Scripts/validation_native.js - extends document shim with createEvent + dispatchEvent.
  • Apps/Playground/Scripts/config.json - re-enables 1 test (idx 342).

Note: Polyfill foundation. Remaining affected playground tests need native dispatchEvent on canvas / Image polyfill / async-module support - out of scope here.

Landing context

This PR is one of 7 splits from the proven CI-green combined preview in draft PR #1702 (see #1702 for the full intended end-state and verified CI run 26044922430).

Note: the original split included an 8th PR (#1709, ES2020+ -> ES2019 syntax-repair polyfill for Chakra). It was closed in favour of investigating @babel/standalone properly (#1711).

Recommended landing order

Tier 1 - parallel-reviewable, no source conflicts:

  1. Fix ExternalTexture_OpenGL throw-stubs to avoid MSVC C4702 under /WX #1703 - ExternalTexture C4702 build fix
  2. Document accurate root cause for post-#1695 pixel-diff fallouts #1704 - config.json reason rewrites (5 entries)
  3. Document accurate root cause for 17 subtle pixel-diff tests #1705 - config.json reason rewrites (17 entries)

Tier 2 - sequential, each touches Apps/Playground/CMakeLists.txt SCRIPTS list + Apps/Playground/Shared/AppContext.cpp LoadScript order; rebase the next branch after the previous merges:

  1. Add File/Blob/FileReader polyfill for Playground (re-enables 19 GLTF tests) #1706 - File/Blob/FileReader polyfill (largest test impact: 19 re-enables)
  2. Add fetch() polyfill over XMLHttpRequest for Playground #1707 - fetch polyfill
  3. Add DOM globals polyfill + native AbortController for Playground #1708 - DOM globals + native AbortController + Android CMake link
  4. Add cubemap auto-expand polyfill for Playground (re-enables 7 PBR tests) #1710 - Cubemap auto-expand polyfill (loaded after babylon.max.js)

Reference policy reminder

Reference PNGs across all 7 PRs come from Babylon.js; never re-baked by BN. Combined diff: 0 PNGs.

bkaradzic-microsoft and others added 2 commits May 15, 2026 21:27
…nt.createEvent)


Playground tests that use modern browser APIs hit ReferenceErrors on
the Chakra-based BN runtime because TextEncoder and PointerEvent are
not part of older Chakra's built-ins. Several serializer tests also
exercise document.createEvent + element.dispatchEvent shapes that the
existing minimal document polyfill in validation_native.js did not
cover.

- Apps/Playground/Scripts/dom_polyfill.js: new self-detecting JS
  polyfills for TextEncoder (UTF-8 encode + encodeInto) and PointerEvent
  (constructor with the MouseEvent + PointerEvent surface).
- Apps/Playground/Shared/AppContext.cpp + CMakeLists.txt: wire in the
  native AbortController polyfill from JsRuntimeHost and load
  dom_polyfill.js before ammo.js.
- Apps/Playground/Scripts/validation_native.js: extend the existing
  document shim with createEvent, dispatchEvent, addEventListener and
  a generic-element fallback for createElement so click-event-based
  serializer tests can run.
- Apps/Playground/Scripts/config.json: re-enable "Serialize scene
  without materials" (idx 342), which now validates with 248 px diff.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
AppContext.cpp includes <Babylon/Polyfills/AbortController.h> and calls
Babylon::Polyfills::AbortController::Initialize(env), but the Android-
specific CMakeLists at Apps/Playground/Android/BabylonNative did not
add AbortController to BabylonNativeJNI's PRIVATE link libraries. The
header is published only by the AbortController target, so Android CI
failed with 'fatal error: Babylon/Polyfills/AbortController.h file not
found'. Linux/macOS/Windows builds were fine because they use the main
Apps/Playground/CMakeLists.txt which already links AbortController.

Mirror the change there so Android picks up the include directory.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds missing DOM-like globals to the Playground JS host and wires up native AbortController so DOM-dependent playgrounds/tests stop throwing ReferenceError.

Changes:

  • Adds a self-detecting TextEncoder + PointerEvent polyfill script and loads it in the Playground startup sequence.
  • Initializes and links the native AbortController polyfill in Playground (including Android JNI link fix).
  • Extends the validation runner’s document shim with createEvent/dispatchEvent and re-enables one previously excluded test.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
Apps/Playground/Shared/AppContext.cpp Initializes native AbortController and loads dom_polyfill.js during startup.
Apps/Playground/Scripts/validation_native.js Expands the document/element shims to support event creation/dispatch used by tests.
Apps/Playground/Scripts/dom_polyfill.js New polyfills for TextEncoder and PointerEvent when absent.
Apps/Playground/Scripts/config.json Re-enables one previously excluded serialization test.
Apps/Playground/CMakeLists.txt Packages dom_polyfill.js and links AbortController into Playground.
Apps/Playground/Android/BabylonNative/CMakeLists.txt Links AbortController into BabylonNativeJNI to fix Android builds.

Comment thread Apps/Playground/Scripts/dom_polyfill.js Outdated
Comment on lines +55 to +58
var arr = this.encode(input);
var n = Math.min(arr.length, dest.length);
for (var i = 0; i < n; i++) dest[i] = arr[i];
return { read: String(input).length, written: n };
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in b79d9db. encodeInto now normalizes input (treats undefined as the empty string) before computing both the encoded bytes and read, so the returned read count is consistent with what encode() writes.

Comment thread Apps/Playground/Scripts/dom_polyfill.js Outdated
init = init || {};
this.type = String(type || '');
this.bubbles = !!init.bubbles;
this.cancelable = init.cancelable !== false;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in b79d9db. cancelable now defaults to false to match the DOM EventInit spec default; callers that need a cancelable event must pass cancelable: true explicitly.

Comment thread Apps/Playground/Scripts/dom_polyfill.js Outdated
Comment on lines +15 to +16
// Chakra has no `globalThis`; use the Function-constructor trick.
var g = (new Function('return this'))();
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in b79d9db. Replaced new Function('return this') with a non-eval resolution chain (globalThis -> self -> window -> global) and kept the Function constructor only as a last-resort fallback for runtimes that ship none of those globals.

- Replace `new Function('return this')` with a non-eval globalThis/self/
  window/global resolution chain; keep the Function-constructor trick
  only as a last-resort fallback for runtimes that ship none of the
  standard globals.
- TextEncoder.prototype.encodeInto: normalize `input` (undefined ->
  empty string) before computing `read`, so the returned read count
  stays consistent with the bytes written by `encode()` (previously
  `String(undefined).length` returned 9 for a zero-byte write).
- PointerEvent.cancelable: default to `false` (DOM spec EventInit
  default) instead of `true`; callers that need a cancelable event
  must pass `cancelable: true` explicitly.

Refs PR BabylonJS#1708.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Member

@ryantrem ryantrem left a comment

Choose a reason for hiding this comment

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

I guess this makes the tests work, but if a consumer tried to use the same things in their own app, they wouldn't work. Is that really the state we want to be in, or we want to know what things don't work because they aren't polyfilled? I would have thought we would either document these features don't work because we don't polyfill, or we add native polyfills for them.

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