Skip to content

Playground: load earcut and procedural textures, and provide name to test scripts - #1823

Open
bkaradzic-microsoft wants to merge 2 commits into
BabylonJS:masterfrom
bkaradzic-microsoft:playground-earcut
Open

Playground: load earcut and procedural textures, and provide name to test scripts#1823
bkaradzic-microsoft wants to merge 2 commits into
BabylonJS:masterfrom
bkaradzic-microsoft:playground-earcut

Conversation

@bkaradzic-microsoft

Copy link
Copy Markdown
Member

Three test failures on the native Playground turned out to have the same root cause: the native harness provides a smaller browser environment than the web Playground, so scripts that work on babylonjs.com die here on a missing global. None of it is renderer-specific, so this fixes the same scenes on both the bgfx and the WebGPU/Dawn paths.

earcut is not defined

PolygonMeshBuilder resolves earcut as a global at triangulation time rather than importing it, so any scene that builds a polygon throws. The web Playground loads earcut as a separate script; we never did.

Pinned to ^2.2.4 deliberately: that is the last line shipping a UMD build (dist/earcut.min.js, which assigns the global). 3.x is ESM-only (exports: ./src/earcut.js, no dist) and cannot be consumed by the plain-script loader.

BABYLON.WoodProceduralTexture is not a constructor

The procedural texture classes live in their own babylonjs-procedural-textures package, which was never in the bundle. The existing config even documents this — one test is disabled with the reason "BABYLON.NormalMapProceduralTexture is not included in the native script bundle".

Wired into BABYLON_SCRIPTS, PlaygroundScripts.cpp, the Android asset copy, and getNightly.js so it stays in step with the other Babylon packages. Pinned to 9.15.0 to match every other babylonjs-* entry in the lock file — on ^9.15.0 npm resolves it to 9.20.0 and then nests a second full copy of babylonjs under it.

name is not defined

Some scripts reference a bare name without declaring it. In a browser that silently resolves to window.name (""), so the bug is invisible on the web but throws here.

Fixed by declaring var name = "" in the function that encloses the eval. Because those are direct evals, the evaluated script sees that scope and resolves name exactly as it would on the web — without leaking a real global, and without rewriting the script text (so line numbers in stack traces and any "use strict" prologue are preserved).

Defining an actual global name is not an option, and I tried: it breaks the Babylon UMD bundles, which probe for name while being evaluated. babylonjs.loaders.js then throws Error: Invalid argument at load time and every test fails.

Validation

Full 680-test sweep on the Dawn/WebGPU backend, before vs. after:

before after
PASS 622 625
FAIL 56 53

Zero regressions. Polygon flips to PASS outright; Procedural textures and Show all procedural textures go from hard exceptions to rendering (they still miss the pixel threshold, tracked separately). The other two deltas (Iridescence NME, Sprite maps) are known order-dependent flakes, not caused by this change.

…o test scripts

Three unrelated-looking test failures all had the same root cause: the native
Playground provides a smaller browser environment than the web Playground, so
scripts that work on the web die here on a missing global.

- `earcut`: PolygonMeshBuilder looks `earcut` up as a global at triangulation
  time rather than importing it, so any polygon scene fails with
  `ReferenceError: earcut is not defined`. Pinned to ^2.2.4 because that is the
  last line shipping a UMD build (`dist/earcut.min.js`); 3.x is ESM-only and
  cannot be loaded by the plain-script loader.

- `babylonjs-procedural-textures`: the procedural texture classes
  (WoodProceduralTexture, BrickProceduralTexture, ...) live in their own package
  which was never loaded, so those scenes failed with
  `BABYLON.WoodProceduralTexture is not a constructor`.

- `name`: some scripts reference `name` without declaring it. In a browser that
  silently resolves to window.name (""), so the bug is invisible there but
  throws `ReferenceError: name is not defined` here. Declared in the scope that
  encloses the eval so a direct eval resolves it exactly as the web does.
  Deliberately *not* defined as a real global: doing that breaks the Babylon UMD
  bundles, which probe for `name` during evaluation and throw at load time.

None of this is renderer-specific; it fixes the same scenes on both the bgfx and
the WebGPU/Dawn paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 88569c10-a7ff-4373-9a58-afa9c68b8c09
Copilot AI lite review requested due to automatic review settings August 7, 2026 15:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Updates the native Playground harness to more closely match the web Playground’s “ambient browser globals” by bundling additional Babylon-related scripts (earcut + procedural textures) and by providing a name binding visible to directly-evaluated test scripts, reducing harness-specific test failures across backends.

Changes:

  • Add earcut.min.js and babylonjs.proceduralTextures.js to the native Playground script bundle and bootstrap load order.
  • Ensure Android asset packaging and the nightly download script include the new Babylon procedural textures artifact.
  • Add a scoped var name = "" binding around direct eval() execution paths in validation_native.js to match browser behavior.

Reviewed changes

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

Show a summary per file
File Description
Apps/scripts/getNightly.js Downloads the procedural textures library artifacts alongside other Babylon nightly files.
Apps/Playground/Shared/PlaygroundScripts.cpp Loads earcut.min.js before polygon scenes run, and loads procedural textures after BABYLON is initialized.
Apps/Playground/Scripts/validation_native.js Introduces a local name binding in eval scopes to prevent ReferenceError: name is not defined for browser-authored scripts.
Apps/Playground/CMakeLists.txt Adds earcut + procedural textures to the packaged script set for native Playground builds.
Apps/Playground/Android/app/build.gradle Copies earcut + procedural textures into Android assets for the Playground app.
Apps/package.json Adds babylonjs-procedural-textures and earcut dependencies for bundling/packaging.
Apps/package-lock.json Locks the new dependencies and their resolved versions.
Files not reviewed (1)
  • Apps/package-lock.json: Generated file

Comment thread Apps/package-lock.json
Comment thread Apps/package.json Outdated
Comment thread Apps/package.json Outdated
… bundle

Addresses review feedback on the earcut/procedural-textures change.

package.json pinned babylonjs-procedural-textures with a caret while the PR
called for an exact pin; on ^9.15.0 npm resolves 9.20.0 and nests a second
full copy of babylonjs underneath it. Pin it exactly, in both package.json
and the lock file's root dependency range, so regenerating the lock file
cannot drift.

getNightly replaces seven babylon*.js bundles but only babylon.max.js was
down-leveled to ES5 afterwards, so the other six ran un-transpiled on
Chakra -- and any bundle added to BABYLON_SCRIPTS later would silently
inherit the same gap. Derive the down-level list from the download table
itself and run it from getNightly.js, so the two can no longer disagree.
Source maps are excluded by the .js anchor.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 88569c10-a7ff-4373-9a58-afa9c68b8c09
@bkaradzic-microsoft

Copy link
Copy Markdown
Member Author

Thanks — all three review comments were valid; pushed in e421e9a.

Exact pin for babylonjs-procedural-textures. Correct catch: the PR description said "pinned to 9.15.0" but package.json carried ^9.15.0. The lock file happened to resolve 9.15.0, so the nesting problem was latent rather than visible — regenerating it would have reintroduced 9.20.0 and the second nested babylonjs copy. Now exact in both package.json and the lock file's root dependency range.

Down-leveling more than babylon.max.js. Also correct, and the gap was wider than the comment suggested: getNightly replaces seven babylon*.js bundles and only babylon.max.js was being down-leveled, so gui, loaders, materials, serializers, addons — and now proceduralTextures — were running un-transpiled on Chakra after a nightly refresh.

Rather than lengthen the hardcoded argument list (which is what let the two drift apart in the first place), the down-level list is now derived from the download table inside getNightly.js and invoked from there, so adding a download can't silently skip the step again. Source maps are excluded by the .js anchor, and downlevelNativeScripts.mjs filters on basename as a second guard. npm run downlevel:native-scripts stays available for manual use.

CI note: Ubuntu_Clang_Hermes SIGSEGV'd on the first run, ~82 tests in. It was a flake — the re-run completed the same 304 tests as master with ran=283 passed=283 failed=0.

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