Skip to content

Add ES2020+ -> ES2019 syntax-repair polyfill for Chakra Playground#1709

Closed
bkaradzic-microsoft wants to merge 1 commit into
BabylonJS:masterfrom
bkaradzic-microsoft:weekend/tpc-1575-chakra-parse
Closed

Add ES2020+ -> ES2019 syntax-repair polyfill for Chakra Playground#1709
bkaradzic-microsoft wants to merge 1 commit into
BabylonJS:masterfrom
bkaradzic-microsoft:weekend/tpc-1575-chakra-parse

Conversation

@bkaradzic-microsoft
Copy link
Copy Markdown
Contributor

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

Adds a lightweight regex-based ES2020+ -> ES2019 syntax-repair polyfill so Chakra-based BN runtimes can parse playgrounds that use modern syntax. V8/JSC runtimes already support these features natively; the polyfill self-detects and no-ops when not needed.

Changes:

  • New Apps/Playground/Scripts/es2019_transpile.js - regex repair for: ?. (optional chaining), ?? (nullish coalescing), numeric separators (incl. hex), ||= &&= ??= (logical assignment). Top-level var __bnTranspileES2019 exposes the helper.
  • Apps/Playground/Scripts/validation_native.js - evalWithFallback catches SyntaxError and retries once with repaired source.
  • Apps/Playground/CMakeLists.txt - adds es2019_transpile.js to SCRIPTS list.
  • Apps/Playground/Shared/AppContext.cpp - loads es2019_transpile.js before fetch_polyfill.js.
  • Apps/Playground/Scripts/config.json - re-enables 1 test (idx 403 custom-handling-of-materials-for-render-target-pass); rewrites reason on 25 remaining-excluded tests with their post-polyfill state.

Caveat: Polyfill is parse-only - ?. rewrites to . so null targets raise TypeError at runtime instead of short-circuiting. 25 tests remain excluded for: 9 runtime TypeErrors from ?. -> . semantic divergence, 4 missing ADDONS module, 8 asset/url errors, 4 ES2022 private fields not handled by the polyfill.

Landing context

This PR is one of 8 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).

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 (3 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 ES2020+ -> ES2019 syntax-repair polyfill for Chakra Playground #1709 - ES2020+ -> ES2019 transpile polyfill
  5. 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 8 PRs come from Babylon.js; never re-baked by BN. Combined diff: 0 PNGs.

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).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why are we doing this with a custom script rather than just using babel or swc or something?

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.

Fair point. Honest assessment of the tradeoff:

  • The custom regex polyfill runs inside the Chakra host at parse-failure time, so a Node-side build tool (babel CLI / swc CLI) wasn't directly usable. The runtime-in-host constraint left us with @babel/standalone (~1 MB shipped + parsed by Chakra at startup), swc-wasm (Chakra doesn't support WASM), or this regex stopgap.
  • The regex is semantically incomplete — ?. rewrites to . so null?.foo throws TypeError instead of returning undefined. That's 9 of the 26 affected tests still excluded because of this divergence, plus 4 more for ES2022 private fields. So this polyfill unlocks only 1 test out of 26.
  • The cost/benefit of "+114 lines for +1 test, with a semantic footgun baked in" is too thin to justify cementing the regex approach.

Closing this PR. Filed #1711 to investigate @babel/standalone properly (measure the actual size/startup cost, prototype, compare against alternatives, decide). If that lands, it would unlock the 9 ?. tests + 4 ES2022 tests correctly, which is a much better story than what this PR achieves.

Thanks for pushing back.

@bkaradzic-microsoft
Copy link
Copy Markdown
Contributor Author

Closing per discussion above. Pursuing #1711 instead.

@bkaradzic-microsoft bkaradzic-microsoft deleted the weekend/tpc-1575-chakra-parse branch May 18, 2026 17:29
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**.
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.

2 participants