Fix(Integration): Load browser manifest via fetch to avoid import attributes - #443
Merged
1aron merged 1 commit intoJul 24, 2026
Conversation
…ributes
The browser manifest facades built a loader with
`new Function('specifier', "return import(specifier, { with: { type: 'json' } })")`.
JSON import attributes (`with { type: 'json' }`) are only supported in Safari
17.2+, Chrome 123+ and Firefox 130+. On older engines, notably every iOS 15
and iOS 16 (Safari < 17.2), evaluating that dynamic import, even inside
`new Function`, throws `SyntaxError: import call expects exactly one argument`
while the entry module is evaluated. Because the manifest facade runs at the
top level of the app entry, the whole app fails to bootstrap and renders a
blank page with no obvious console error.
The syntax is invisible to build-time tooling because it lives inside a
`new Function` string, so bundler and esbuild target checks never flag it.
Load the manifest with `fetch().then(r => r.json())` in the browser facades
(`toBrowserManifestFacadeModule` and the browser branch of
`toUniversalManifestFacadeModule`). Fetch is universally supported and needs no
bundler-hiding indirection. The Node facades keep the JSON import attribute,
since Node supports it. Verified on an iOS 15.5 Safari simulator: blank before,
mounts after.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@0Miles is attempting to deploy a commit to the Aoyue Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
Pull request overview
This PR updates the @master/css-integration manifest facade generators to avoid JSON import attributes in browser runtime facades, preventing Safari < 17.2 (iOS 15/16) from failing module evaluation and rendering a blank page at app bootstrap.
Changes:
- Switch the browser manifest facade generator to load the manifest via
fetch(...).json()instead of a JSON import attribute hidden behindnew Function. - Update the universal facade generator’s browser branch to use the same
fetch-based loader (renaming the helper accordingly). - Extend integration tests to assert the browser facade avoids import attributes (and
new Function) and that the universal facade’s browser branch usesfetch.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| packages/integration/src/manifest-facade.ts | Replaces browser-side JSON import-attribute loading with a fetch(...).json() loader in browser and universal facades. |
| packages/integration/tests/module.test.ts | Adds assertions to prevent regressions back to import attributes / new Function for browser manifest loading. |
Comments suppressed due to low confidence (1)
packages/integration/src/manifest-facade.ts:103
loadMasterCSSManifestFromFetchreturnsresponse.json()without validatingresponse.ok. If the manifest URL 404s (or returns an HTML error page), this will throw a low-signal JSON parse error instead of a clear fetch failure. Add an OK check and throw an explicit error including status + URL.
`async function loadMasterCSSManifestFromFetch(url) {`,
` const specifier = typeof url === 'string' ? url : url.href;`,
` const response = await fetch(specifier);`,
` return response.json();`,
`}`,
Comment on lines
+54
to
+55
| `const masterCSSManifestResponse = await fetch(typeof masterCSSManifestURL === 'string' ? masterCSSManifestURL : masterCSSManifestURL.href);`, | ||
| `export default await masterCSSManifestResponse.json();`, |
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Apps using Master CSS in runtime mode render a blank page with no obvious console error on Safari < 17.2 — which includes every iOS 15 and iOS 16 device (iOS 16 tops out at 16.7).
The browser manifest facades generate a loader like:
JSON import attributes (
import(url, { with: { type: 'json' } })) are only supported in Safari 17.2+, Chrome 123+, Firefox 130+. On older engines, evaluating that dynamic import — even insidenew Function— throws:Because the manifest facade runs at the top level of the app entry module, this aborts entry evaluation, so the framework never mounts and the page stays blank. There's no clear console error, which makes it very hard to diagnose.
It's also invisible to build-time checks: the syntax lives inside a
new Functionstring, so esbuild/Rollup/Vite target scans never parse or flag it. (I spent a while scanning bundles with--target=safari16and they all reported "clean" for exactly this reason.)Fix
Load the manifest with
fetch(...).then(r => r.json())in the two browser facades:toBrowserManifestFacadeModuletoUniversalManifestFacadeModule(renamedloadMasterCSSManifestFromImport→loadMasterCSSManifestFromFetch)fetchis universally supported and needs nonew Functionbundler-hiding indirection. The Node facades (toNodeManifestFacadeModuleand theloadMasterCSSManifestFromFilebranch) keep the JSON import attribute, since Node supports it and those paths only run whentypeof window === 'undefined'.Verification
packages/integrationtests updated + a browser-facade regression test added; full suite passes (12/12), type-check and lint clean.Notes
rel="modulepreload" as="json"(hardcoded across the vite/webpack/nuxt/astro integrations). It's harmless with afetchload but slightly inconsistent; happy to follow up separately to switch it torel="preload" as="fetch"if you'd prefer.