Skip to content

Bump JsRuntimeHost for File/FileReader polyfill (re-enables 19 GLTF/OBJ tests)#1706

Open
bkaradzic-microsoft wants to merge 7 commits into
BabylonJS:masterfrom
bkaradzic-microsoft:weekend/tpc-1582-file-api
Open

Bump JsRuntimeHost for File/FileReader polyfill (re-enables 19 GLTF/OBJ tests)#1706
bkaradzic-microsoft wants to merge 7 commits into
BabylonJS:masterfrom
bkaradzic-microsoft:weekend/tpc-1582-file-api

Conversation

@bkaradzic-microsoft
Copy link
Copy Markdown
Contributor

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

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), 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: "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 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.cppBabylon::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 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. Bump JsRuntimeHost for File/FileReader polyfill (re-enables 19 GLTF/OBJ tests) #1706 - File/FileReader polyfill (JsRuntimeHost bump + Playground wiring; 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 5 commits May 15, 2026 20:58
BabylonNative's native JsRuntimeHost ships a Blob C++ ObjectWrap but no
File constructor or FileReader. Several Babylon.js serializer round-trip
tests (GLTF/OBJ export then re-load) use new File([blob], 'scene.glb') and
rely on the loader's FilesInputStore path that internally invokes
FileReader.readAsArrayBuffer. Without these the tests fail with
ReferenceError: 'File' is not defined / 'FileReader' is not defined.

Adds a self-detecting JS polyfill that:
 - no-ops on runtimes that already expose File/FileReader (V8, JSC may)
 - no-ops when the native Blob polyfill is missing
 - decorates a native Blob with name/lastModified to produce a File
   (deliberately without setPrototypeOf - pivoting the napi ObjectWrap
   prototype strips its bound instance methods on Chakra)
 - implements FileReader on top of Blob.arrayBuffer() with readAsArrayBuffer,
   readAsText, readAsDataURL, readAsBinaryString and the standard event
   surface (onload/onerror/onloadend, addEventListener/removeEventListener)

Hooked into Playground via SCRIPTS in Apps/Playground/CMakeLists.txt and
loaded from AppContext.cpp before ammo.js / babylon.max.js.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Re-enables tests at indices 208-216, 219-226, 275, 276 in
Apps/Playground/Scripts/config.json (GLTF Serializer round-trip variants
and OBJ Stanford Bunny round-trip in both handednesses), which were
previously excluded with "Pixel comparison fails (more than 20% pixels
differ)" or "File API not available" reasons. The actual root cause was
the missing File/FileReader globals, now addressed in the previous commit.

All 19 tests verified passing via headless Playground runner without
--include-excluded.

Updates reasons for tests that still fail with the polyfill present:
 - idx 217 (Draco mesh compression): Draco loader uses 'utf8' encoding name
   which Babylon Native's TextDecoder polyfill rejects (only 'utf-8' OK)
 - idx 277, 278 (glTF to OBJ round trip): hangs on Win32 Chakra D3D11

Remaining still-excluded entries (218, 227-230, 420, 421) keep their
existing pixel-diff reasons; they are unrelated to the File polyfill.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Linux JSC and GCC CI runners (OpenGL backend) hit a 3.4% pixel diff
(8097/240000 px) on this test that does not appear on the D3D11 backend.
The test was re-enabled by the file-api branch because it passes on
Win32 D3D11, but the OpenGL backend has a separate rendering issue
that is out of scope for the File API polyfill work. Mark the test
excludedGraphicsApis=[OpenGL] so it still runs on D3D11/D3D12/Metal/
Vulkan and stays skipped on OpenGL.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Same pattern as KHR gpu instancing: the Camera serializer roundtrip
test diverges on the OpenGL backend (Linux JSC and GCC CI runners,
~21% pixel diff with the rendered clear color showing through where
the geometry should be) but passes on D3D11. Exclude on OpenGL while
we figure out the backend-specific issue.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CI continues to surface the same OpenGL-only rendering issue on every
test using playgroundId #O0M0J9#25 (the Camera serializer roundtrip):
- left-handed (already excluded last round)
- right-handed (failed this round, ~50K px diff)
- left-handed, round trip twice
- right-handed, round trip twice

All share the same scene and codepath. Mark the remaining 3 with
excludedGraphicsApis=[OpenGL] preemptively so we stop iterating one
test at a time on this same failure mode. Tests still run on D3D11/
D3D12/Metal/Vulkan.

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 a JS-side File / FileReader polyfill to Babylon Native’s Playground so GLTF serializer/loader round-trip tests can run under the BN JS runtime again.

Changes:

  • Introduces file_polyfill.js implementing File (as a decorated native Blob) and a Promise-backed FileReader.
  • Loads the polyfill early in Playground startup and includes it in the CMake scripts bundle.
  • Re-enables previously excluded serializer-related tests and refines exclusions/reasons for known backend issues.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 7 comments.

File Description
Apps/Playground/Shared/AppContext.cpp Loads the new File API polyfill before other scripts.
Apps/Playground/Scripts/file_polyfill.js Adds minimal File + FileReader implementations on top of the native Blob.
Apps/Playground/Scripts/config.json Re-enables many tests; adds targeted OpenGL exclusions and updates a few “reason” strings.
Apps/Playground/CMakeLists.txt Ensures the new polyfill script is packaged with existing Playground scripts.

Comment thread Apps/Playground/Scripts/file_polyfill.js Outdated
Comment thread Apps/Playground/Scripts/file_polyfill.js Outdated
Comment thread Apps/Playground/Scripts/file_polyfill.js Outdated
Comment thread Apps/Playground/Scripts/file_polyfill.js Outdated
Comment thread Apps/Playground/Scripts/file_polyfill.js Outdated
Comment thread Apps/Playground/Scripts/file_polyfill.js Outdated
Comment thread Apps/Playground/Scripts/config.json Outdated
FileReader changes:
- abort() now invalidates the in-flight read via a monotonic `_readId`
  token; the .then continuation in startRead() captures the token and
  early-returns if it has moved on, so a late-resolving arrayBuffer()
  promise can no longer clobber state or dispatch a phantom `load`
  after a user-initiated abort.
- readAsText now prefers TextDecoder first and falls back to a chunked
  String.fromCharCode.apply + Array.join path. The previous code built
  a byte-by-byte `s += c` string and then often discarded it; for
  multi-MB GLTF JSON this was the most expensive path in the polyfill.
- dispatchEvent(event) routes through the existing internal dispatch()
  helper so on* handlers and addEventListener listeners actually fire
  for the event type, instead of returning true and dropping the event.

Config change:
- Rewrite the Draco/utf8 reason text to scope the limitation correctly:
  it is BN's TextDecoder (no WHATWG label normalization) that rejects
  `utf8`, not Web TextDecoder in general.

Refs PR BabylonJS#1706.

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.

Should we not just add File support to the actual native Blob polyfill?

Copy link
Copy Markdown
Contributor

@bghgary bghgary left a comment

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]

File and FileReader are standard web APIs that Babylon.js code paths depend on (GLTF serializer round-trip). This should be a proper C++ polyfill under Polyfills/ so every consumer gets it, not a Playground-only JS script.

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 bkaradzic-microsoft changed the title Add File/Blob/FileReader polyfill for Playground (re-enables 19 GLTF tests) File/FileReader C++ polyfill (re-enables 19 GLTF/OBJ tests) May 26, 2026
bkaradzic-microsoft pushed a commit to bkaradzic-microsoft/BabylonNative that referenced this pull request May 26, 2026
Addresses @bghgary's review on BabylonJS#1706: File and FileReader are standard
WHATWG web APIs that Babylon.js code paths depend on (GLTF serializer
round-trip uses `new File([blob], 'scene.glb')` then
`LoadAssetContainerAsync` which internally reads via
`FileReader.readAsArrayBuffer`). The polyfills now live in
JsRuntimeHost (next to `Polyfills/Blob/`) so every JsRuntimeHost
consumer gets them, not just BabylonNative.

The JsRuntimeHost-side change is at
bkaradzic-microsoft/JsRuntimeHost@670084e5 ("Add File / FileReader
polyfill"). This temporarily points BabylonNative's FetchContent at
that fork branch; once the upstream JsRuntimeHost PR lands, we will
re-pin to the merged commit on BabylonJS/JsRuntimeHost.

Babylon Native side:
  - `CMakeLists.txt`: bump JsRuntimeHost GIT_TAG to `670084e5` and
    point GIT_REPOSITORY at the bkaradzic-microsoft fork until the
    upstream JsRuntimeHost PR is merged.
  - `Apps/Playground/Shared/AppContext.cpp`: include
    `<Babylon/Polyfills/File.h>` and call
    `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`: drop `file_polyfill.js` from
    SCRIPTS, link 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).

Verified by running the GLTF/OBJ serializer round-trip tests that this
PR re-enables (indices 208-216, 219-226, 275-276): 19/19 pass on
Win32 D3D11 Release headless.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bkaradzic-microsoft bkaradzic-microsoft force-pushed the weekend/tpc-1582-file-api branch from 18d0b82 to 93d7053 Compare May 26, 2026 18:04
@bkaradzic-microsoft bkaradzic-microsoft changed the title File/FileReader C++ polyfill (re-enables 19 GLTF/OBJ tests) Bump JsRuntimeHost for File/FileReader polyfill (re-enables 19 GLTF/OBJ tests) May 26, 2026
bkaradzic-microsoft pushed a commit to bkaradzic-microsoft/BabylonNative that referenced this pull request May 26, 2026
Addresses @bghgary's review on BabylonJS#1706: File and FileReader are standard
WHATWG web APIs that Babylon.js code paths depend on (GLTF serializer
round-trip uses `new File([blob], 'scene.glb')` then
`LoadAssetContainerAsync` which internally reads via
`FileReader.readAsArrayBuffer`). The polyfills now live in
JsRuntimeHost (next to `Polyfills/Blob/`) so every JsRuntimeHost
consumer gets them, not just BabylonNative.

The JsRuntimeHost-side change is at
bkaradzic-microsoft/JsRuntimeHost@670084e5 ("Add File / FileReader
polyfill"). This temporarily points BabylonNative's FetchContent at
that fork branch; once the upstream JsRuntimeHost PR lands, we will
re-pin to the merged commit on BabylonJS/JsRuntimeHost.

Babylon Native side:
  - `CMakeLists.txt`: bump JsRuntimeHost GIT_TAG to `670084e5` and
    point GIT_REPOSITORY at the bkaradzic-microsoft fork until the
    upstream JsRuntimeHost PR is merged.
  - `Apps/Playground/Shared/AppContext.cpp`: include
    `<Babylon/Polyfills/File.h>` and call
    `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`: drop `file_polyfill.js` from
    SCRIPTS, link 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).

Verified by running the GLTF/OBJ serializer round-trip tests that this
PR re-enables (indices 208-216, 219-226, 275-276): 19/19 pass on
Win32 D3D11 Release headless.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bkaradzic-microsoft bkaradzic-microsoft force-pushed the weekend/tpc-1582-file-api branch from 93d7053 to 8644cf5 Compare May 26, 2026 18:07
@bkaradzic-microsoft bkaradzic-microsoft force-pushed the weekend/tpc-1582-file-api branch from e87aaed to 5b1983e Compare May 26, 2026 19:13
bkaradzic-microsoft pushed a commit to bkaradzic-microsoft/JsRuntimeHost that referenced this pull request May 26, 2026
Implements `File` and `FileReader` as Napi::ObjectWrap-based polyfills,
matching the rest of `JsRuntimeHost/Polyfills/`. Lives next to `Blob`
because `File` is layered directly on top of `Blob` (delegates byte
storage to the global `Blob` constructor, then decorates the instance
with `name` / `lastModified`).

Why JsRuntimeHost: `File` and `FileReader` are standard WHATWG web APIs
in the same category as the existing `XMLHttpRequest`, `URL`,
`WebSocket`, `TextDecoder`, `AbortController`, etc. polyfills. Hosting
them here means every JsRuntimeHost embedder (BabylonNative and
others) gets them for free, rather than each consumer reimplementing.

Polyfills/File/:
  - File: Napi::ObjectWrap that delegates byte storage to the native
    Blob polyfill (constructs an inner Blob via the global constructor
    so it stays in lockstep with whatever Blob the runtime exposes) and
    layers `name` / `lastModified` on top. size/type/arrayBuffer/text/
    bytes forward to the inner Blob.
  - FileReader: full ObjectWrap with readAsArrayBuffer / readAsText /
    readAsDataURL / readAsBinaryString, addEventListener /
    removeEventListener / dispatchEvent, on{load,error,loadstart,
    loadend,progress,abort} handler slots, EMPTY/LOADING/DONE state
    constants, and abort() honored via a monotonic readId token so a
    late-resolving arrayBuffer() promise can't dispatch a phantom load
    after the user aborted. The single base64 call site
    (readAsDataURL) uses an inlined RFC 4648 encoder to avoid pulling
    in a third-party dep just for this polyfill.
  - Initialize() is self-detecting: no-op when globalThis.File already
    exists, and no-op when globalThis.Blob is missing (so Blob::Initialize
    must run first - documented in Readme.md).

Wiring:
  - CMakeLists.txt: new `JSRUNTIMEHOST_POLYFILL_FILE` option (ON by
    default), placed next to the existing `_BLOB` / `_PERFORMANCE`
    options.
  - Polyfills/CMakeLists.txt: `if(JSRUNTIMEHOST_POLYFILL_FILE)
    add_subdirectory(File) endif()` between Blob and Performance.

Verified end-to-end via BabylonNative's GLTF/OBJ serializer
round-trip tests (BabylonJS/BabylonNative#1706): 19/19 pass on Win32
D3D11 Release headless (test indices 208-216, 219-226, 275-276).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
bkaradzic-microsoft pushed a commit to bkaradzic-microsoft/BabylonNative that referenced this pull request May 26, 2026
Addresses @bghgary's review on BabylonJS#1706: File and FileReader are standard
WHATWG web APIs that Babylon.js code paths depend on (GLTF serializer
round-trip uses `new File([blob], 'scene.glb')` then
`LoadAssetContainerAsync` which internally reads via
`FileReader.readAsArrayBuffer`). The polyfills now live in
JsRuntimeHost (next to `Polyfills/Blob/`) so every JsRuntimeHost
consumer gets them, not just BabylonNative.

The JsRuntimeHost-side change is at
bkaradzic-microsoft/JsRuntimeHost@670084e5 ("Add File / FileReader
polyfill"). This temporarily points BabylonNative's FetchContent at
that fork branch; once the upstream JsRuntimeHost PR lands, we will
re-pin to the merged commit on BabylonJS/JsRuntimeHost.

Babylon Native side:
  - `CMakeLists.txt`: bump JsRuntimeHost GIT_TAG to `670084e5` and
    point GIT_REPOSITORY at the bkaradzic-microsoft fork until the
    upstream JsRuntimeHost PR is merged.
  - `Apps/Playground/Shared/AppContext.cpp`: include
    `<Babylon/Polyfills/File.h>` and call
    `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`: drop `file_polyfill.js` from
    SCRIPTS, link 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).

Verified by running the GLTF/OBJ serializer round-trip tests that this
PR re-enables (indices 208-216, 219-226, 275-276): 19/19 pass on
Win32 D3D11 Release headless.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bkaradzic-microsoft bkaradzic-microsoft force-pushed the weekend/tpc-1582-file-api branch from 5b1983e to e6da978 Compare May 26, 2026 19:37
bkaradzic-microsoft pushed a commit to bkaradzic-microsoft/BabylonNative that referenced this pull request May 26, 2026
Addresses @bghgary's review on BabylonJS#1706: File and FileReader are standard
WHATWG web APIs that Babylon.js code paths depend on (GLTF serializer
round-trip uses `new File([blob], 'scene.glb')` then
`LoadAssetContainerAsync` which internally reads via
`FileReader.readAsArrayBuffer`). The polyfills now live in
JsRuntimeHost (next to `Polyfills/Blob/`) so every JsRuntimeHost
consumer gets them, not just BabylonNative.

The JsRuntimeHost-side change is at
bkaradzic-microsoft/JsRuntimeHost@670084e5 ("Add File / FileReader
polyfill"). This temporarily points BabylonNative's FetchContent at
that fork branch; once the upstream JsRuntimeHost PR lands, we will
re-pin to the merged commit on BabylonJS/JsRuntimeHost.

Babylon Native side:
  - `CMakeLists.txt`: bump JsRuntimeHost GIT_TAG to `670084e5` and
    point GIT_REPOSITORY at the bkaradzic-microsoft fork until the
    upstream JsRuntimeHost PR is merged.
  - `Apps/Playground/Shared/AppContext.cpp`: include
    `<Babylon/Polyfills/File.h>` and call
    `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`: drop `file_polyfill.js` from
    SCRIPTS, link 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).

Verified by running the GLTF/OBJ serializer round-trip tests that this
PR re-enables (indices 208-216, 219-226, 275-276): 19/19 pass on
Win32 D3D11 Release headless.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bkaradzic-microsoft bkaradzic-microsoft force-pushed the weekend/tpc-1582-file-api branch from e6da978 to d0c96ef Compare May 26, 2026 19:43
bkaradzic-microsoft pushed a commit to bkaradzic-microsoft/BabylonNative that referenced this pull request May 26, 2026
The File polyfill was previously shipped as a JS shim
(Apps/Playground/Scripts/file_polyfill.js, ~308 lines) and registered
via LoadScript from AppContext. Per review on PR BabylonJS#1706 it now lives
as a proper C++ polyfill in JsRuntimeHost alongside Blob, URL,
WebSocket, XMLHttpRequest, etc., so every JsRuntimeHost consumer
gets File / FileReader -- not only the Playground.

This change:
* Bumps the JsRuntimeHost FetchContent pin to the commit that adds
  Polyfills/File + unit tests.
* Calls Babylon::Polyfills::File::Initialize(env) right after
  Babylon::Polyfills::Blob::Initialize(env) in AppContext.
* Drops the file_polyfill.js shim and its LoadScript call.
* Links the new File polyfill target in both the desktop and
  Android Playground CMakeLists.

Re-enables 19 GLTF / OBJ tests that previously depended on the JS
shim (208-216, 219-226, 275-276).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bkaradzic-microsoft bkaradzic-microsoft force-pushed the weekend/tpc-1582-file-api branch from 7e60faf to 2d1c4ac Compare May 26, 2026 23:18
bkaradzic-microsoft pushed a commit to bkaradzic-microsoft/BabylonNative that referenced this pull request May 26, 2026
The File polyfill was previously shipped as a JS shim
(Apps/Playground/Scripts/file_polyfill.js, ~308 lines) and registered
via LoadScript from AppContext. Per review on PR BabylonJS#1706 it now lives
as a proper C++ polyfill in JsRuntimeHost alongside Blob, URL,
WebSocket, XMLHttpRequest, etc., so every JsRuntimeHost consumer
gets File / FileReader -- not only the Playground.

This change:
* Bumps the JsRuntimeHost FetchContent pin to the commit that adds
  Polyfills/File + unit tests.
* Calls Babylon::Polyfills::File::Initialize(env) right after
  Babylon::Polyfills::Blob::Initialize(env) in AppContext.
* Drops the file_polyfill.js shim and its LoadScript call.
* Links the new File polyfill target in both the desktop and
  Android Playground CMakeLists.

Re-enables 19 GLTF / OBJ tests that previously depended on the JS
shim (208-216, 219-226, 275-276).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bkaradzic-microsoft bkaradzic-microsoft force-pushed the weekend/tpc-1582-file-api branch from 2d1c4ac to 7cfdd7b Compare May 26, 2026 23:32
bkaradzic-microsoft pushed a commit to bkaradzic-microsoft/BabylonNative that referenced this pull request May 27, 2026
The File polyfill was previously shipped as a JS shim
(Apps/Playground/Scripts/file_polyfill.js, ~308 lines) and registered
via LoadScript from AppContext. Per review on PR BabylonJS#1706 it now lives
as a proper C++ polyfill in JsRuntimeHost alongside Blob, URL,
WebSocket, XMLHttpRequest, etc., so every JsRuntimeHost consumer
gets File / FileReader -- not only the Playground.

This change:
* Bumps the JsRuntimeHost FetchContent pin to the commit that adds
  Polyfills/File + unit tests.
* Calls Babylon::Polyfills::File::Initialize(env) right after
  Babylon::Polyfills::Blob::Initialize(env) in AppContext.
* Drops the file_polyfill.js shim and its LoadScript call.
* Links the new File polyfill target in both the desktop and
  Android Playground CMakeLists.

Re-enables 19 GLTF / OBJ tests that previously depended on the JS
shim (208-216, 219-226, 275-276).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bkaradzic-microsoft bkaradzic-microsoft force-pushed the weekend/tpc-1582-file-api branch from 7cfdd7b to 7395246 Compare May 27, 2026 00:01
bkaradzic-microsoft pushed a commit to bkaradzic-microsoft/BabylonNative that referenced this pull request May 27, 2026
The File polyfill was previously shipped as a JS shim
(Apps/Playground/Scripts/file_polyfill.js, ~308 lines) and registered
via LoadScript from AppContext. Per review on PR BabylonJS#1706 it now lives
as a proper C++ polyfill in JsRuntimeHost alongside Blob, URL,
WebSocket, XMLHttpRequest, etc., so every JsRuntimeHost consumer
gets File / FileReader -- not only the Playground.

This change:
* Bumps the JsRuntimeHost FetchContent pin to the commit that adds
  Polyfills/File + unit tests.
* Calls Babylon::Polyfills::File::Initialize(env) right after
  Babylon::Polyfills::Blob::Initialize(env) in AppContext.
* Drops the file_polyfill.js shim and its LoadScript call.
* Links the new File polyfill target in both the desktop and
  Android Playground CMakeLists.

Re-enables 19 GLTF / OBJ tests that previously depended on the JS
shim (208-216, 219-226, 275-276).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bkaradzic-microsoft bkaradzic-microsoft force-pushed the weekend/tpc-1582-file-api branch from 7395246 to e5538fe Compare May 27, 2026 01:02
bkaradzic-microsoft pushed a commit to bkaradzic-microsoft/BabylonNative that referenced this pull request May 27, 2026
The File polyfill was previously shipped as a JS shim
(Apps/Playground/Scripts/file_polyfill.js, ~308 lines) and registered
via LoadScript from AppContext. Per review on PR BabylonJS#1706 it now lives
as a proper C++ polyfill in JsRuntimeHost alongside Blob, URL,
WebSocket, XMLHttpRequest, etc., so every JsRuntimeHost consumer
gets File / FileReader -- not only the Playground.

This change:
* Bumps the JsRuntimeHost FetchContent pin to the commit that adds
  Polyfills/File + unit tests.
* Calls Babylon::Polyfills::File::Initialize(env) right after
  Babylon::Polyfills::Blob::Initialize(env) in AppContext.
* Drops the file_polyfill.js shim and its LoadScript call.
* Links the new File polyfill target in both the desktop and
  Android Playground CMakeLists.

Re-enables 19 GLTF / OBJ tests that previously depended on the JS
shim (208-216, 219-226, 275-276).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bkaradzic-microsoft bkaradzic-microsoft force-pushed the weekend/tpc-1582-file-api branch from e5538fe to 4fa0e35 Compare May 27, 2026 01:09
bkaradzic-microsoft pushed a commit to bkaradzic-microsoft/BabylonNative that referenced this pull request May 27, 2026
The File polyfill was previously shipped as a JS shim
(Apps/Playground/Scripts/file_polyfill.js, ~308 lines) and registered
via LoadScript from AppContext. Per review on PR BabylonJS#1706 it now lives
as a proper C++ polyfill in JsRuntimeHost alongside Blob, URL,
WebSocket, XMLHttpRequest, etc., so every JsRuntimeHost consumer
gets File / FileReader -- not only the Playground.

This change:
* Bumps the JsRuntimeHost FetchContent pin to the commit that adds
  Polyfills/File + unit tests.
* Calls Babylon::Polyfills::File::Initialize(env) right after
  Babylon::Polyfills::Blob::Initialize(env) in AppContext.
* Drops the file_polyfill.js shim and its LoadScript call.
* Links the new File polyfill target in both the desktop and
  Android Playground CMakeLists.

Re-enables 19 GLTF / OBJ tests that previously depended on the JS
shim (208-216, 219-226, 275-276).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bkaradzic-microsoft bkaradzic-microsoft force-pushed the weekend/tpc-1582-file-api branch from 4fa0e35 to 8e47055 Compare May 27, 2026 01:28
bkaradzic-microsoft pushed a commit to bkaradzic-microsoft/BabylonNative that referenced this pull request May 27, 2026
The File polyfill was previously shipped as a JS shim
(Apps/Playground/Scripts/file_polyfill.js, ~308 lines) and registered
via LoadScript from AppContext. Per review on PR BabylonJS#1706 it now lives
as a proper C++ polyfill in JsRuntimeHost alongside Blob, URL,
WebSocket, XMLHttpRequest, etc., so every JsRuntimeHost consumer
gets File / FileReader -- not only the Playground.

This change:
* Bumps the JsRuntimeHost FetchContent pin to the commit that adds
  Polyfills/File + unit tests.
* Calls Babylon::Polyfills::File::Initialize(env) right after
  Babylon::Polyfills::Blob::Initialize(env) in AppContext.
* Drops the file_polyfill.js shim and its LoadScript call.
* Links the new File polyfill target in both the desktop and
  Android Playground CMakeLists.

Re-enables 19 GLTF / OBJ tests that previously depended on the JS
shim (208-216, 219-226, 275-276).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bkaradzic-microsoft bkaradzic-microsoft force-pushed the weekend/tpc-1582-file-api branch from 8e47055 to 5eb7f89 Compare May 27, 2026 01:39
bkaradzic-microsoft pushed a commit to bkaradzic-microsoft/BabylonNative that referenced this pull request May 27, 2026
The File polyfill was previously shipped as a JS shim
(Apps/Playground/Scripts/file_polyfill.js, ~308 lines) and registered
via LoadScript from AppContext. Per review on PR BabylonJS#1706 it now lives
as a proper C++ polyfill in JsRuntimeHost alongside Blob, URL,
WebSocket, XMLHttpRequest, etc., so every JsRuntimeHost consumer
gets File / FileReader -- not only the Playground.

This change:
* Bumps the JsRuntimeHost FetchContent pin to the commit that adds
  Polyfills/File + unit tests.
* Calls Babylon::Polyfills::File::Initialize(env) right after
  Babylon::Polyfills::Blob::Initialize(env) in AppContext.
* Drops the file_polyfill.js shim and its LoadScript call.
* Links the new File polyfill target in both the desktop and
  Android Playground CMakeLists.

Re-enables 19 GLTF / OBJ tests that previously depended on the JS
shim (208-216, 219-226, 275-276).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bkaradzic-microsoft bkaradzic-microsoft force-pushed the weekend/tpc-1582-file-api branch from 5eb7f89 to c5606b0 Compare May 27, 2026 01:49
bkaradzic-microsoft pushed a commit to bkaradzic-microsoft/BabylonNative that referenced this pull request May 27, 2026
The File polyfill was previously shipped as a JS shim
(Apps/Playground/Scripts/file_polyfill.js, ~308 lines) and registered
via LoadScript from AppContext. Per review on PR BabylonJS#1706 it now lives
as a proper C++ polyfill in JsRuntimeHost alongside Blob, URL,
WebSocket, XMLHttpRequest, etc., so every JsRuntimeHost consumer
gets File / FileReader -- not only the Playground.

This change:
* Bumps the JsRuntimeHost FetchContent pin to the commit that adds
  Polyfills/File + unit tests.
* Calls Babylon::Polyfills::File::Initialize(env) right after
  Babylon::Polyfills::Blob::Initialize(env) in AppContext.
* Drops the file_polyfill.js shim and its LoadScript call.
* Links the new File polyfill target in both the desktop and
  Android Playground CMakeLists.

Re-enables 19 GLTF / OBJ tests that previously depended on the JS
shim (208-216, 219-226, 275-276).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bkaradzic-microsoft bkaradzic-microsoft force-pushed the weekend/tpc-1582-file-api branch from c5606b0 to 31c15fc Compare May 27, 2026 02:03
bkaradzic-microsoft pushed a commit to bkaradzic-microsoft/BabylonNative that referenced this pull request May 27, 2026
The File polyfill was previously shipped as a JS shim
(Apps/Playground/Scripts/file_polyfill.js, ~308 lines) and registered
via LoadScript from AppContext. Per review on PR BabylonJS#1706 it now lives
as a proper C++ polyfill in JsRuntimeHost alongside Blob, URL,
WebSocket, XMLHttpRequest, etc., so every JsRuntimeHost consumer
gets File / FileReader -- not only the Playground.

This change:
* Bumps the JsRuntimeHost FetchContent pin to the commit that adds
  Polyfills/File + unit tests.
* Calls Babylon::Polyfills::File::Initialize(env) right after
  Babylon::Polyfills::Blob::Initialize(env) in AppContext.
* Drops the file_polyfill.js shim and its LoadScript call.
* Links the new File polyfill target in both the desktop and
  Android Playground CMakeLists.

Re-enables 19 GLTF / OBJ tests that previously depended on the JS
shim (208-216, 219-226, 275-276).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bkaradzic-microsoft bkaradzic-microsoft force-pushed the weekend/tpc-1582-file-api branch from 31c15fc to 75abaa5 Compare May 27, 2026 03:53
The File polyfill was previously shipped as a JS shim
(Apps/Playground/Scripts/file_polyfill.js, ~308 lines) and registered
via LoadScript from AppContext. Per review on PR BabylonJS#1706 it now lives
as a proper C++ polyfill in JsRuntimeHost alongside Blob, URL,
WebSocket, XMLHttpRequest, etc., so every JsRuntimeHost consumer
gets File / FileReader -- not only the Playground.

This change:
* Bumps the JsRuntimeHost FetchContent pin to the commit that adds
  Polyfills/File + unit tests.
* Calls Babylon::Polyfills::File::Initialize(env) right after
  Babylon::Polyfills::Blob::Initialize(env) in AppContext.
* Drops the file_polyfill.js shim and its LoadScript call.
* Links the new File polyfill target in both the desktop and
  Android Playground CMakeLists.

Re-enables 19 GLTF / OBJ tests that previously depended on the JS
shim (208-216, 219-226, 275-276).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bkaradzic-microsoft bkaradzic-microsoft force-pushed the weekend/tpc-1582-file-api branch from 75abaa5 to 7867db2 Compare May 27, 2026 04:11
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>
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.

5 participants