Skip to content

Commit 777eb73

Browse files
committed
Load the Emscripten glue through an indirection
Metro refuses a non-literal import() at build time, and the webpackIgnore comment that was there to excuse it does not survive babel-preset-expo, which strips it before Metro's dependency collector ever sees it. So an Expo web app did not fail against this package at runtime, it failed to build at all, and every such consumer had to patch the published dist to get past it. Putting the call inside a string leaves nothing for a bundler to parse and nothing to strip. It needs unsafe-eval, which is why importGlue stays the documented way out for a page under a strict CSP. The docstring above it claimed bundlers chunk the glue. They never did, since webpackIgnore told them not to.
1 parent 0030a0c commit 777eb73

2 files changed

Lines changed: 18 additions & 4 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ surprised by it.
1616

1717
### Fixed before publishing
1818

19-
Two things that would each have made this release wrong.
19+
Three things that would each have made this release wrong.
2020

2121
The binary shipped Helvetica, baked into `viro-web.data` by the preload step and
2222
therefore redistributed with the package. It renders in **Roboto** now, which is
@@ -30,6 +30,15 @@ existed in `types.ts` and in no build. Every one of them would have been
3030
`undefined` at runtime. Rebuilt from virocore; the package's own test now
3131
checks all 126, and that the preloaded font is one this package may ship.
3232

33+
And the glue module could not be bundled by Metro. `loadViroWebModule` reached
34+
it through a variable specifier, which Metro refuses at build time, and the
35+
`webpackIgnore` comment that was there to excuse it is stripped by
36+
`babel-preset-expo` before Metro's dependency collector runs. So an Expo web app
37+
did not fail at runtime against this package, it failed to build at all. The
38+
import goes through an indirection now, which no bundler parses. That
39+
indirection needs `unsafe-eval`, so a page under a strict CSP should pass
40+
`importGlue` instead.
41+
3342
### Added
3443

3544
- **The tracking engine ships with the package.** Web AR needed a second WASM

‎src/loader.ts‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ function resolveAssetBase(baseUrl?: string): string {
2222
/**
2323
* Load and instantiate the WASM renderer module.
2424
*
25-
* The Emscripten glue (viro-web.js) is imported dynamically so bundlers treat it
26-
* as an async chunk and the ~2MB payload is only fetched on demand. The
25+
* The Emscripten glue (viro-web.js) is fetched from the asset base at runtime
26+
* rather than bundled, so the ~2MB payload is only paid for on demand. The
2727
* .wasm/.data sidecars are located from the same base (see resolveAssetBase).
2828
*/
2929
export interface LoadOptions {
@@ -50,7 +50,12 @@ export async function loadViroWebModule(
5050
imported = await opts.importGlue();
5151
} else {
5252
const glueUrl = base + "viro-web.js";
53-
imported = await import(/* webpackIgnore: true */ /* @vite-ignore */ glueUrl);
53+
// Indirect so no bundler parses a non-literal import(). Metro rejects one
54+
// outright, and strips the webpackIgnore comment before it would help.
55+
const importModule = new Function("u", "return import(u)") as (
56+
u: string,
57+
) => Promise<{ default?: ViroWebModuleFactory } | ViroWebModuleFactory>;
58+
imported = await importModule(glueUrl);
5459
}
5560

5661
const factory = ((imported as { default?: ViroWebModuleFactory }).default ??

0 commit comments

Comments
 (0)