In a type-only specifier where the local name is literally as, the emitted Identifier node carries the span of the as keyword (the second as token) instead of the span of the identifier itself (the first as token). The identifier's name is correct, only start/end are wrong.
Repro (oxc-parser 0.140.0):
import { parseSync } from "oxc-parser";
const src = "export { type as as if };";
// 0123456789...
// ^type=9 ^as=14 ^as=17 ^if=20
const { program } = parseSync("x.ts", src, { sourceType: "module" });
console.log(JSON.stringify(program.body[0].specifiers[0], null, 2));
Actual:
{
"type": "ExportSpecifier",
"local": { "type": "Identifier", "name": "as", "start": 17, "end": 19 },
"exported": { "type": "Identifier", "name": "if", "start": 20, "end": 22 },
"exportKind": "type",
"start": 9,
"end": 22
}
local points at 17-19, which is the second as, the one serving as the rename keyword. That reading is internally inconsistent: it leaves no token between local (ends 19) and exported (starts 20) to act as the as keyword.
Expected: local should span 14-16 (the first as), with the second as (17-19) being the keyword. Babel and yuku both parse it this way: a type-only export specifier with local (as) at 14-16 and exported (if) at 20-22.
export { type as as if };
^^^^ type-only modifier
^^ local (14-16)
^^ keyword (17-19)
^^ exported (20-22)
AST explorer: oxc (actual) vs yuku (expected)
The import form has the same bug:
parseSync("x.ts", `import { type as as x } from "m";`, { sourceType: "module" });
// imported: { name: "as", start: 17, end: 19 } (should be start: 14, end: 16)
In a type-only specifier where the local name is literally
as, the emittedIdentifiernode carries the span of theaskeyword (the secondastoken) instead of the span of the identifier itself (the firstastoken). The identifier'snameis correct, onlystart/endare wrong.Repro (
oxc-parser0.140.0):Actual:
{ "type": "ExportSpecifier", "local": { "type": "Identifier", "name": "as", "start": 17, "end": 19 }, "exported": { "type": "Identifier", "name": "if", "start": 20, "end": 22 }, "exportKind": "type", "start": 9, "end": 22 }localpoints at 17-19, which is the secondas, the one serving as the rename keyword. That reading is internally inconsistent: it leaves no token betweenlocal(ends 19) andexported(starts 20) to act as theaskeyword.Expected:
localshould span 14-16 (the firstas), with the secondas(17-19) being the keyword. Babel and yuku both parse it this way: a type-only export specifier withlocal(as) at 14-16 andexported(if) at 20-22.AST explorer: oxc (actual) vs yuku (expected)
The import form has the same bug: