-
Notifications
You must be signed in to change notification settings - Fork 30.4k
Description
Link to the code that reproduces this issue
https://github.com/veniceai/turbopack-safari-reserved-words-repro
To Reproduce
-
Clone the repo and install dependencies:
git clone https://github.com/veniceai/turbopack-safari-reserved-words-repro
cd turbopack-safari-reserved-words-repro
npm install -
Build with Turbopack:
npm run build -
Verify the output chunks contain unquoted reserved words:
npm run verify
(This finds 7 violations: {const:, let:, var:} as unquoted object keys in AJV chunks) -
Start the production server and open in Safari 15 / iOS 15 (e.g. via BrowserStack):
npm start
Open http://localhost:3000 -
Safari 15 console shows:
SyntaxError: Unexpected keyword 'var'. Expected '}' to end an object literal.
The bug is in turbopack-ecmascript/src/transform/mod.rs — PropertyLiterals and
MemberExpressionLiterals are excluded from preset_env alongside ReservedWords.
Only ReservedWords needs to be excluded (it breaks module resolution). The other
two are safe and are needed to quote reserved-word property names for Safari 15.
Current vs. Expected behavior
● ## Current behavior
Turbopack production builds (next build --turbo) emit unquoted reserved words
as object property names in JS chunks. For example, AJV's codegen/scope.js:
exports.varKinds = {const: new Name("const"), let: new Name("let"), var: new Name("var")}
Safari 15 / iOS 15 parses ES modules in strict mode, and its parser incorrectly
rejects unquoted reserved words as property names with:
SyntaxError: Unexpected keyword 'var'. Expected '}' to end an object literal.
SyntaxError: Unexpected keyword 'let'. Cannot use 'let' as an identifier name for a LexicalDeclaration.
This affects any dependency that uses reserved words as object keys. Common ones
include ajv, @chakra-ui/styled-system, framer-motion, and mingo.
The root cause is in turbopack-ecmascript/src/transform/mod.rs where three ES3
transforms are excluded from preset_env:
exclude: vec![
FeatureOrModule::Feature(Feature::ReservedWords),
FeatureOrModule::Feature(Feature::MemberExpressionLiterals),
FeatureOrModule::Feature(Feature::PropertyLiterals),
]
ReservedWords must be excluded (it breaks Turbopack's module resolution), but
PropertyLiterals and MemberExpressionLiterals are safe — they only affect
property name quoting, not identifier resolution.
Expected behavior
Turbopack should quote reserved-word property names in output chunks:
exports.varKinds = {"const": new Name("const"), "let": new Name("let"), "var": new Name("var")}
This is what webpack/Babel builds produce via @babel/plugin-transform-property-literals,
and what SWC's swc_ecma_compat_es3::prop_lits transform does when enabled.
The fix is to only exclude ReservedWords from preset_env, leaving PropertyLiterals
and MemberExpressionLiterals enabled:
exclude: vec![
FeatureOrModule::Feature(Feature::ReservedWords),
]
iOS 15 / Safari 15 still has ~5-8% mobile market share. All Turbopack production
builds are broken for these users if any dependency uses reserved words as
property names.
Provide environment information
Operating System:
Platform: linux
Arch: arm64
Version: #1 SMP Thu Jan 15 14:58:53 UTC 2026
Available memory (MB): 19972
Available CPU cores: 16
Binaries:
Node: 20.20.0
npm: 10.8.2
Yarn: 1.22.22
pnpm: 10.29.2
Relevant Packages:
next: 16.2.0-canary.35 // Latest available version is detected (16.2.0-canary.35).
eslint-config-next: N/A
react: 19.2.4
react-dom: 19.2.4
typescript: 5.9.3
Next.js Config:
output: N/AWhich area(s) are affected? (Select all that apply)
Turbopack
Which stage(s) are affected? (Select all that apply)
Vercel (Deployed)
Additional context
No response