parser: false "Duplicated export" when await appears in variable initializer under .js auto-detect
export var x = await + 1; produces a spurious Duplicated export 'x' error when parsed with a .js filename (sourceType auto-detection). The same source parses cleanly with .mjs or explicit sourceType: 'module'.
Reproduction
Playground link
Steps:
mkdir /tmp/oxc-repro && cd /tmp/oxc-repro
npm init -y
npm install oxc-parser
node -e "
const { parseSync } = require('oxc-parser');
const src = 'export var x = await + 1;';
// ✗ .js auto-detect: false 'Duplicated export'
const r1 = parseSync('input.js', src);
console.log('.js auto-detect:', r1.errors.length ? 'ERROR: ' + r1.errors[0].message : 'OK');
// ✓ .mjs: works fine
const r2 = parseSync('input.mjs', src);
console.log('.mjs:', r2.errors.length ? 'ERROR: ' + r2.errors[0].message : 'OK');
// ✓ .js with explicit sourceType: works fine
const r3 = parseSync('input.js', src, { sourceType: 'module' });
console.log('.js + sourceType=module:', r3.errors.length ? 'ERROR: ' + r3.errors[0].message : 'OK');
// ✓ .js with prior module syntax: works fine
const r4 = parseSync('input.js', 'export {}; ' + src);
console.log('.js + prior export:', r4.errors.length ? 'ERROR: ' + r4.errors[0].message : 'OK');
"
Expected output:
.js auto-detect: OK
.mjs: OK
.js + sourceType=module: OK
.js + prior export: OK
Actual output (oxc-parser 0.129.0):
.js auto-detect: ERROR: Duplicated export 'x'
.mjs: OK
.js + sourceType=module: OK
.js + prior export: OK
V8 cross-check (confirming it's valid JS):
echo 'export var x = await + 1;' > /tmp/test.js
node --check /tmp/test.js && echo "V8: OK" || echo "V8: ERROR"
# → V8: OK
echo 'export var x = await + 1;' > /tmp/test.mjs
node --check /tmp/test.mjs && echo "V8: OK" || echo "V8: ERROR"
# → V8: OK
Analysis
The bug fires when all three conditions hold:
.js filename (auto-detect mode, not .mjs or explicit sourceType)
export is the first module syntax in the file (no prior import/export)
await appears in the variable initializer
The AST itself is correct — the body contains a single ExportNamedDeclaration with one declarator initialized to an AwaitExpression — but the duplicate-export check fires against what appears to be a stale pre-upgrade binding. Both labels in the error codeframe point at the same x identifier.
Other await patterns also trigger the bug:
export var x = await(1); // ✗ Duplicated export 'x'
export var x = await + 0; // ✗ Duplicated export 'x'
Non-await initializers do not:
export var x = 1 + 1; // ✓
export var x = void 0; // ✓
export var x = yield + 1; // ✓
Spec reference
ECMA-262 §16.2.3: export VariableStatement binds the declared names as exports. In module code, await is a keyword (§16.2), so await + 1 is parsed as await (+1) — a top-level AwaitExpression of the unary expression +1. The result is a single VariableDeclaration with one binding x. There is no duplicate.
Parser matrix
| Parser |
Version |
export var x = await + 1; |
| V8 (node --check, .js) |
v25.9.0 |
✅ accepts |
| V8 (node --check, .mjs) |
v25.9.0 |
✅ accepts |
| Acorn |
latest |
✅ accepts |
| Babel (sourceType: unambiguous) |
7.29.3 |
✅ accepts |
| TypeScript |
6.0.3 |
✅ accepts |
| SWC |
1.15.33 |
✅ accepts |
| esbuild |
0.28.0 |
✅ accepts |
| OXC (.mjs) |
0.129.0 |
✅ accepts |
| OXC (sourceType: module) |
0.129.0 |
✅ accepts |
| OXC (.js auto-detect) |
0.129.0 |
❌ Duplicated export |
parser: false "Duplicated export" when
awaitappears in variable initializer under.jsauto-detectexport var x = await + 1;produces a spuriousDuplicated export 'x'error when parsed with a.jsfilename (sourceType auto-detection). The same source parses cleanly with.mjsor explicitsourceType: 'module'.Reproduction
Playground link
Steps:
Expected output:
Actual output (oxc-parser 0.129.0):
V8 cross-check (confirming it's valid JS):
Analysis
The bug fires when all three conditions hold:
.jsfilename (auto-detect mode, not.mjsor explicitsourceType)exportis the first module syntax in the file (no priorimport/export)awaitappears in the variable initializerThe AST itself is correct — the body contains a single
ExportNamedDeclarationwith one declarator initialized to anAwaitExpression— but the duplicate-export check fires against what appears to be a stale pre-upgrade binding. Both labels in the error codeframe point at the samexidentifier.Other
awaitpatterns also trigger the bug:Non-
awaitinitializers do not:Spec reference
ECMA-262 §16.2.3:
exportVariableStatement binds the declared names as exports. In module code,awaitis a keyword (§16.2), soawait + 1is parsed asawait (+1)— a top-levelAwaitExpressionof the unary expression+1. The result is a singleVariableDeclarationwith one bindingx. There is no duplicate.Parser matrix
export var x = await + 1;