Skip to content

[draft] Playground polyfills: File/FileReader, DOM, fetch, cubemap .env, Chakra ES2019#1702

Draft
bkaradzic-microsoft wants to merge 5 commits into
BabylonJS:masterfrom
bkaradzic-microsoft:weekend/all-combined
Draft

[draft] Playground polyfills: File/FileReader, DOM, fetch, cubemap .env, Chakra ES2019#1702
bkaradzic-microsoft wants to merge 5 commits into
BabylonJS:masterfrom
bkaradzic-microsoft:weekend/all-combined

Conversation

@bkaradzic-microsoft
Copy link
Copy Markdown
Contributor

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

Rebased onto latest master. Several pieces of the original combined branch have landed independently and were dropped as superseded; the genuine remaining playground-polyfill features stay.

Kept (5 commits, all unique to this branch)

  • DOM polyfills (dom_polyfill.js: TextEncoder, PointerEvent, AbortController, document.createEvent) + Android JNI link for the AbortController polyfill.
  • fetch() polyfill (fetch_polyfill.js).
  • Cubemap .env fallback (cube_texture_polyfill.js) + re-enable of 7 cubemap tests.
  • Chakra ES2020→ES2019 syntax-repair polyfill (es2019_transpile.js).

All four polyfills are wired through AppContext.cpp's script loader (transpiler first, then DOM/fetch; the cubemap patch loads after Babylon since it patches NativeEngine.createCubeTexture) and registered in Apps/Playground/CMakeLists.txt.

Dropped (now in master)

config.json validates as JSON, identical structure to master apart from the cubemap re-enables and the ES2019/cubemap reason-string rewrites.

Note: the Chakra ES2019 syntax-repair polyfill remains here as part of the full intended preview, but the standalone split for it (#1709) was closed in favour of investigating @babel/standalone properly (#1711). Treat that piece as exploratory.

@bkaradzic-microsoft bkaradzic-microsoft force-pushed the weekend/all-combined branch 3 times, most recently from 0707eaf to 61da57f Compare May 18, 2026 16:00
bkaradzic-microsoft added a commit that referenced this pull request May 21, 2026
Per-test PIL-composite triage of all 17 ``subtle pixel-diff`` tests.
None of them are deterministic-cosmetic (no re-bakes possible - all show
real visible regressions).

Updates the `reason` field in `Apps/Playground/Scripts/config.json` for
17 tests with accurate symptom descriptions, classifying into recurring
root-cause clusters:

- 9 GUI green->red color regressions (idx 160, 174, 175, 196, 197, 370,
402, 566, 587)
- 4 OpenPBR analytic-lights right-column red rendering (580, 584, 587,
592)
- 1 instanced billboard foliage red (169)
- 1 LineEdgesRenderer extra red lines (179)
- 1 Background blur red splotches (602)
- 1 Clip planes GUI sliders red (182)
- 1 Instanced Bones edge-AA (256, borderline)

**No source changes, no test re-enables, no PNGs.** Metadata-only
correction so the issue tracker reflects actionable root causes.
---

## Landing context

This PR is one of **7 splits** from the proven CI-green combined preview
in **draft PR #1702** (see
[#1702](#1702) for the
full intended end-state and verified CI run
[26044922430](https://github.com/BabylonJS/BabylonNative/actions/runs/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. #1703 - ExternalTexture C4702 build fix
2. #1704 - config.json `reason` rewrites (5 entries)
3. #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:**

4. #1706 - File/Blob/FileReader polyfill (largest test impact: 19
re-enables)
5. #1707 - fetch polyfill
6. #1708 - DOM globals + native AbortController + Android CMake link
7. #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 added a commit that referenced this pull request May 21, 2026
Per-test triage of 5 post-#1695 pixel-diff fallouts. Updates the
`reason` field in `Apps/Playground/Scripts/config.json` for 3 entries to
name the real BN rendering regression instead of generic "Pixel
comparison fails":

- idx 363 SSR2 - SSR not rendering wet floor.
- idx 369 Sprites Pixel Perfect - sprite alpha-blending broken.
- idx 395 soft-transparent-shadows - soft-shadow filter precision
degraded.

**No source changes, no test re-enables, no PNGs.** Metadata-only
correction so the issue tracker reflects actionable root causes for
follow-up engineering work.
---

## Landing context

This PR is one of **7 splits** from the proven CI-green combined preview
in **draft PR #1702** (see
[#1702](#1702) for the
full intended end-state and verified CI run
[26044922430](https://github.com/BabylonJS/BabylonNative/actions/runs/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. #1703 - ExternalTexture C4702 build fix
2. #1704 - config.json `reason` rewrites (5 entries)
3. #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:**

4. #1706 - File/Blob/FileReader polyfill (largest test impact: 19
re-enables)
5. #1707 - fetch polyfill
6. #1708 - DOM globals + native AbortController + Android CMake link
7. #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 added a commit that referenced this pull request May 28, 2026
…1703)

Fixes MSVC C4702 (unreachable code) under `/WX` in
`Plugins/ExternalTexture/Source/ExternalTexture_OpenGL.cpp` so the
OpenGL TU builds cleanly without the project-wide `/wd4702` workaround.

## What changed

`Plugins/ExternalTexture/Source/ExternalTexture_OpenGL.cpp` keeps the
unimplemented `Impl` stubs as `throw std::runtime_error{"not
implemented"}` (so callers get an unambiguous diagnostic matching every
other backend's unimplemented path) and wraps the `#include
"ExternalTexture_Shared.h"` line in `#pragma warning(push)/(disable:
4702)/(pop)`. The shared dispatchers instantiated by that include
unconditionally call the stubs, so MSVC's flow analysis flags the
dispatcher's post-call code as unreachable; the pragma suppresses C4702
only for the dispatcher code instantiated in this translation unit. Any
other code in this file is still subject to `/WX` C4702 enforcement.

`Plugins/ExternalTexture/CMakeLists.txt` - drop the `/wd4702` target
compile option, which previously silenced C4702 across the whole target.

## Alternatives considered

- **`[[noreturn]]` on the stubs**: MSVC propagates "never returns"
through the shared dispatcher, which flags *more* post-call statements
as unreachable. Tried and rejected (it made the warning worse).
- **TU-wide `/wd4702` via `target_compile_options`**: silences any
future legitimate C4702 elsewhere in the same TU, defeating `/WX`. The
current localized `#pragma warning(push/pop)` block keeps the rest of
the TU under `/WX` enforcement.
- **Replacing the throws with inert return-default stubs**: changes
product behaviour (callers would silently receive a null texture instead
of a clear "not implemented" error) to work around a compiler warning.
Rejected on principle.

## Verified

Clean under Debug + Release + RelWithDebInfo on OpenGL (`win32-gl`,
`GRAPHICS_API=OpenGLWindowsDevOnly`) and D3D11 (`win32`).

---

## Landing context

This PR is one of **7 splits** from the proven CI-green combined preview
in **draft PR #1702** (see
[#1702](#1702) for the
full intended end-state and verified CI run
[26044922430](https://github.com/BabylonJS/BabylonNative/actions/runs/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. #1703 - ExternalTexture C4702 build fix
2. #1704 - config.json `reason` rewrites (5 entries)
3. #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:**

4. #1706 - File/Blob/FileReader polyfill (largest test impact: 19
re-enables)
5. #1707 - fetch polyfill
6. #1708 - DOM globals + native AbortController + Android CMake link
7. #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**.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bkaradzic-microsoft bkaradzic-microsoft changed the title [draft] Combined weekend playground polyfills (CI smoke) [draft] Playground polyfills: File/FileReader, DOM, fetch, cubemap .env, Chakra ES2019 Jun 4, 2026
bkaradzic-microsoft added a commit that referenced this pull request Jun 5, 2026
…BJ tests) (#1706)

Re-enables the 19 GLTF/OBJ serializer round-trip tests that fail under
BN today because the runtime is missing `File` and `FileReader`.
Babylon.js code paths (`new File([blob], 'scene.glb')` followed by
`LoadAssetContainerAsync(file, scene)`, which internally reads via
`FileReader.readAsArrayBuffer`) need both APIs to work.

The actual polyfill **lives in JsRuntimeHost**
([bkaradzic-microsoft/JsRuntimeHost @
670084e5](bkaradzic-microsoft/JsRuntimeHost@670084e)),
next to `Polyfills/Blob/`. That's the architecturally correct home —
`File` and `FileReader` are standard WHATWG web APIs in the same
category as the existing `XMLHttpRequest` / `URL` / `WebSocket` /
`TextDecoder` / `AbortController` polyfills hosted there, and `File` is
layered directly on top of `Blob`. Hosting them there means every
JsRuntimeHost consumer (BN and any other embedder) gets them.

> Addresses [@bghgary's
review](#1706 (review)):
_"this should be a proper C++ polyfill under `Polyfills/` so every
consumer gets it, not a Playground-only JS script"_.

**This PR (BN-side) is intentionally tiny:**
- `CMakeLists.txt` — bump JsRuntimeHost `GIT_TAG` to `670084e5` and
temporarily point `GIT_REPOSITORY` at the
[`bkaradzic-microsoft/JsRuntimeHost`](https://github.com/bkaradzic-microsoft/JsRuntimeHost)
fork until the upstream JsRuntimeHost PR is merged. Will be re-pinned to
a `BabylonJS/JsRuntimeHost` commit before this PR merges.
- `Apps/Playground/Shared/AppContext.cpp` —
`Babylon::Polyfills::File::Initialize(env)` immediately after
`Blob::Initialize(env)`. The old
`LoadScript("app:///Scripts/file_polyfill.js")` line is gone.
- `Apps/Playground/CMakeLists.txt` — drops `file_polyfill.js` from
SCRIPTS, links the new JsRuntimeHost `File` target into the Playground
binary.
- `Apps/Playground/Scripts/file_polyfill.js` — deleted (308 lines of JS
subsumed by the C++ polyfill in JsRuntimeHost).
- `Apps/Playground/Scripts/config.json` — re-enables 19 affected tests;
adds `excludedGraphicsApis: ["OpenGL"]` to 5 GLTF Serializer tests (KHR
gpu instancing + 4 Camera variants) for OpenGL-specific backend issues
unrelated to this polyfill.

**Verified:** 19/19 affected tests pass on Win32 D3D11 Release headless
without `--include-excluded` (indices 208-216, 219-226, 275-276).
Remaining 9 (in the same family) fail with separate root causes —
tracked separately.

## Landing sequence

1. ✅ Push JsRuntimeHost work to fork branch + this BN PR (← here,
validating CI against fork branch).
2. ⏳ Open PR to `BabylonJS/JsRuntimeHost` adding `Polyfills/File/` once
BN CI is green here.
3. ⏳ After the JsRuntimeHost PR merges, re-pin this BN PR's
`GIT_REPOSITORY` / `GIT_TAG` back to `BabylonJS/JsRuntimeHost` at the
merged SHA.
4. ⏳ Merge this BN PR.

---

## Series landing context

This PR is one of **7 splits** from the proven CI-green combined preview
in **draft PR #1702** (see
[#1702](#1702) for the
full intended end-state and verified CI run
[26044922430](https://github.com/BabylonJS/BabylonNative/actions/runs/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. #1703 - ExternalTexture C4702 build fix
2. #1704 - config.json `reason` rewrites (5 entries)
3. #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:**

4. #1706 - File/FileReader polyfill (JsRuntimeHost bump + Playground
wiring; largest test impact: 19 re-enables)
5. #1707 - fetch polyfill
6. #1708 - DOM globals + native AbortController + Android CMake link
7. #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**.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Branimir Karadzic <branimirkaradzic@gmail.com>
bkaradzic-microsoft and others added 5 commits June 5, 2026 16:30
…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>
Implements a minimal `fetch(input, init)` polyfill in Apps/Playground that
wraps XMLHttpRequest. Provides a Response-like result with
`.ok`, `.status`, `.statusText`, `.url`, `.text()`, `.arrayBuffer()`,
`.json()`, `.blob()`, and a `headers` stub. Self-detecting: no-op if a
global `fetch` already exists; bails if XMLHttpRequest is unavailable.

Wired into the Playground SCRIPTS list and loaded by AppContext before
`ammo.js` / `babylon.max.js` so playground snippets that use the modern
`fetch` API can run on Babylon Native's host environments (Chakra and V8),
which do not provide `fetch` by default.

Babylon Native's `XMLHttpRequest` only dispatches events through
`addEventListener` (no `onload`/`onerror` properties) and fires
`loadend` rather than `load`; the polyfill listens on `loadend` and
inspects `status` to decide resolve/reject. When `responseType` is
`arraybuffer`, BN's `XHR.responseText` is empty, so `.text()` decodes
the array buffer directly rather than reading `responseText`.
Babylon Native's NativeEngine.createCubeTexture override only handles
.env single-file cubemaps and 6-face arrays; .dds / .ktx / .ktx2 URLs
fall through to a throw ("Cannot load cubemap because 6 files were not
defined"). The loader-aware path used by the WebGL engine (texture
loader registry lookup) is bypassed entirely.

Add a JS-side polyfill that detects .dds / .ktx / .ktx2 single-URL
cubemap loads and retries with the .env extension. Babylon's CI
generates both .dds and .env from the same source HDR and uploads
them to the same CDN path, so the swap is transparent for the
Babylon-hosted environments these tests reference. On 404 (no .env
counterpart exists) the polyfill re-invokes the original code path,
preserving the existing throw semantics.

This unblocks 7 tests that were excluded because the throw aborted
the scene before any rendering could happen:

  idx 141 NMEGLTF
  idx 172 Anisotropic
  idx 173 Clear Coat
  idx 246 PBRMetallicRoughnessMaterial
  idx 247 PBRSpecularGlossinessMaterial
  idx 248 PBR
  idx 290 Prepass SSAO + depth of field

Strip excludeFromAutomaticTesting + reason from those 7 entries in
config.json. All 7 validate sub-threshold on Win32 V8 D3D11 Release
without --include-excluded after the strip (pixel diff range
308..2638, well under the 2.5% threshold).
Babylon Native's Chakra-based builds parse only up to ES2019; modern
Babylon.js playground snippets routinely use optional chaining (?.),
nullish coalescing (??), numeric separators (1_000_000), and logical
assignment (||= &&= ??=), causing 26 visual tests to fail with
SyntaxError at the eval() site in validation_native.js.

Add a lightweight regex-based syntax-repair polyfill loaded before
babylon.max.js. The polyfill exposes __bnTranspileES2019(code) as a
top-level global var. validation_native.js's new evalWithFallback
helper catches SyntaxError on the first eval and retries once with
the repaired source. Engines that already accept the source (V8,
JSC) never hit the retry path.

The polyfill is syntax-only (parse-time fix), not semantic - ?. is
rewritten to . so a null target throws TypeError at runtime instead
of short-circuiting to undefined. This is a deliberate trade-off:
parse failures are 100% blocking; runtime TypeErrors are diagnosable
and at worst surface a different bug that was previously hidden.

Strip excludeFromAutomaticTesting from idx 403
(custom-handling-of-materials-for-render-target-pass) which now
passes end-to-end. Updated reasons for the other 25 entries to
describe their post-polyfill state: 9 hit runtime errors after
parse repair, 12 hit asset/module gaps, 4 hit ES2022 syntax not
covered by the polyfill (e.g. private class fields).
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