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.

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