mirror of
https://github.com/aphrody-labs/oxc.git
synced 2026-10-17 12:56:09 +00:00
fix(packages/codegen): support printing V8IntrinsicExpressions (#27597)
`oxc_codegen` (Rust) supports printing `V8IntrinsicExpression`s but `oxc-codegen` (JS) didn't. Add support for it.
This commit is contained in:
1 parent
0c98dc54ac
commit
0353d37faf
2 files changed
+58
-1
No files matched your search
@@ -248,6 +248,9 @@ export function printExpression(
|
||||
printTSTypeAssertion(node, state, precedence, ctx);
|
||||
break;
|
||||
/* END_IF */
|
||||
case "V8IntrinsicExpression":
|
||||
printV8IntrinsicExpression(node, state, precedence, ctx);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown expression type: ${node.type}`);
|
||||
}
|
||||
@@ -365,7 +368,7 @@ function printCallExpression(
|
||||
* Arguments print at `PREC_COMMA`, so a sequence expression parenthesizes itself instead of reading as more arguments.
|
||||
*/
|
||||
function printArguments(
|
||||
node: ESTree.CallExpression | ESTree.NewExpression,
|
||||
node: ESTree.CallExpression | ESTree.NewExpression | ESTree.V8IntrinsicExpression,
|
||||
args: ESTree.Argument[],
|
||||
state: State,
|
||||
): void {
|
||||
@@ -1029,3 +1032,26 @@ function printChainExpression(
|
||||
printExpression(node.expression, state, precedence, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A V8 runtime call, e.g. `%DebugPrint(x)`, which the parser only produces with its `allowV8Intrinsics` option.
|
||||
*
|
||||
* Parenthesized wherever a postfix operator follows it - a member access, a call or a tagged template -
|
||||
* and under `new`, as `oxc_codegen` does: `(%DebugPrint(x)).y`.
|
||||
*/
|
||||
function printV8IntrinsicExpression(
|
||||
node: ESTree.V8IntrinsicExpression,
|
||||
state: State,
|
||||
precedence: number,
|
||||
ctx: number,
|
||||
): void {
|
||||
const wrap = precedence >= PREC_POSTFIX || (ctx & CTX_FORBID_CALL) !== 0;
|
||||
if (wrap) write(state, "(", CAT_OTHER);
|
||||
|
||||
writeWithMap(state, "%", CAT_OTHER, node.start, node.end, node);
|
||||
const { name } = node;
|
||||
writeWithMapNamed(state, name.name, name.start, name.end, name);
|
||||
printArguments(node, node.arguments, state);
|
||||
|
||||
if (wrap) write(state, ")", CAT_CLOSE_BRACKET);
|
||||
}
|
||||
@@ -78,6 +78,14 @@ const call = (callee: ESTree.Expression, args: ESTree.Argument[] = []) =>
|
||||
arguments: args,
|
||||
optional: false,
|
||||
});
|
||||
const newExpr = (callee: ESTree.Expression, args: ESTree.Argument[] = []) =>
|
||||
node<ESTree.NewExpression>({ type: "NewExpression", callee, arguments: args });
|
||||
const v8 = (name: string, args: ESTree.Argument[] = []) =>
|
||||
node<ESTree.V8IntrinsicExpression>({
|
||||
type: "V8IntrinsicExpression",
|
||||
name: node<ESTree.IdentifierName>({ type: "Identifier", name }),
|
||||
arguments: args,
|
||||
});
|
||||
const unary = (operator: ESTree.UnaryOperator, argument: ESTree.Expression) =>
|
||||
node<ESTree.UnaryExpression>({ type: "UnaryExpression", operator, argument, prefix: true });
|
||||
const update = (
|
||||
@@ -479,6 +487,29 @@ describe("for-of heads starting with `async` or `let`", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
// V8 runtime calls, e.g. `%DebugPrint(x)`. The parser only produces them with its `allowV8Intrinsics` option,
|
||||
// which neither `oxc-parser`'s Node.js API nor the conformance binding exposes, so only a hand-built AST reaches
|
||||
// them. Each expected output is what `oxc_codegen` prints for the same source, parsed with `allow_v8_intrinsics`.
|
||||
describe("V8 intrinsics", () => {
|
||||
const debugPrint = () => v8("DebugPrint", [id("x")]);
|
||||
|
||||
checkCases([
|
||||
["statement", e(debugPrint()), "%DebugPrint(x);\n"],
|
||||
["no-args", e(v8("DebugPrint")), "%DebugPrint();\n"],
|
||||
["string-arg", e(v8("DebugPrint", [str("hi")])), '%DebugPrint("hi");\n'],
|
||||
["nested", e(v8("DebugPrint", [v8("GetFoo"), id("x")])), "%DebugPrint(%GetFoo(), x);\n"],
|
||||
// Parenthesized where a postfix operator follows, and under `new`
|
||||
["member", e(member(debugPrint(), id("y"))), "(%DebugPrint(x)).y;\n"],
|
||||
["computed-member", e(computedMember(debugPrint(), num(0))), "(%DebugPrint(x))[0];\n"],
|
||||
["callee", e(call(debugPrint())), "(%DebugPrint(x))();\n"],
|
||||
["new-callee", e(newExpr(debugPrint())), "new (%DebugPrint(x))();\n"],
|
||||
// Not parenthesized as an operand or an argument
|
||||
["unary-operand", e(unary("!", debugPrint())), "!%DebugPrint(x);\n"],
|
||||
["binary-operand", e(bin("+", debugPrint(), num(1))), "%DebugPrint(x) + 1;\n"],
|
||||
["argument", e(call(id("f"), [debugPrint()])), "f(%DebugPrint(x));\n"],
|
||||
]);
|
||||
});
|
||||
|
||||
// The three `export default` declaration forms - interface, class and function - each end with a
|
||||
// newline, so whatever follows starts on its own line. `export default interface` printed without
|
||||
// one until `oxc_codegen` was fixed, gluing the next statement onto the closing brace.
|
||||
|
||||
Reference in new issue
Block a user