mirror of
https://github.com/aphrody-labs/oxc.git
synced 2026-10-15 06:39:17 +00:00
docs(parser): document AST property order (#27038)
## Summary - document the property order emitted by `oxc-parser` - explain `visitorKeys` traversal order and why it is not alphabetical - add an order-sensitive `Object.keys` regression test ## Test - `pnpm test-node run test/visit.test.ts` (12 tests passed) ## AI assistance Codex was used to help implement and draft this change. The contributor reviewed the resulting code and documentation and takes full responsibility for the submission.
This commit is contained in:
2 files changed
+45
No files matched your search
@@ -31,6 +31,26 @@ The only differences between Oxc's AST and ESTree / TS-ESTree are:
|
||||
That aside, the AST should completely align with Acorn's ESTree AST or TS-ESLint's TS-ESTree.
|
||||
Any deviation would be considered a bug.
|
||||
|
||||
#### Property order
|
||||
|
||||
ESTree and TS-ESTree do not define an order for node properties. `oxc-parser` emits them in this
|
||||
order:
|
||||
|
||||
1. `type`.
|
||||
2. Node-specific fields in Oxc's defined serialization order. Properties containing child nodes
|
||||
have the same relative order as the entries in `visitorKeys[node.type]`.
|
||||
3. `start`, then `end`.
|
||||
4. `range`, when the `range` option is enabled.
|
||||
|
||||
`visitorKeys` is an exported map from a node type to the properties containing that node's children,
|
||||
in traversal order. For example, `visitorKeys.ConditionalExpression` is
|
||||
`['test', 'consequent', 'alternate']`. This is not alphabetical order: walking `alternate` before
|
||||
`test` would not match the syntax or evaluation order of a conditional expression.
|
||||
|
||||
Fields omitted by the selected `astType` do not change the relative order of the remaining fields.
|
||||
A generic walker which recursively inspects `Object.keys(node)` therefore visits standard ESTree
|
||||
children in the same relative order as Oxc's `Visitor` and the exported `visitorKeys`.
|
||||
|
||||
### AST Types
|
||||
|
||||
[@oxc-project/types](https://npmx.dev/package/@oxc-project/types) can be used. For example:
|
||||
|
||||
@@ -262,3 +262,28 @@ it("visitor keys", () => {
|
||||
expect(visitorKeys.ParenthesizedExpression).toEqual(["expression"]);
|
||||
expect(visitorKeys.V8IntrinsicExpression).toEqual(["name", "arguments"]);
|
||||
});
|
||||
|
||||
it("emits node keys in a stable order", () => {
|
||||
const { program } = parseSync(
|
||||
"test.ts",
|
||||
"const fn = async <T>(arg: T): Promise<T> => await arg;",
|
||||
);
|
||||
const [declaration] = program.body;
|
||||
if (declaration.type !== "VariableDeclaration") throw new Error("Expected variable declaration");
|
||||
const [{ init }] = declaration.declarations;
|
||||
if (init?.type !== "ArrowFunctionExpression") throw new Error("Expected arrow function");
|
||||
|
||||
expect(Object.keys(init)).toStrictEqual([
|
||||
"type",
|
||||
"expression",
|
||||
"async",
|
||||
"typeParameters",
|
||||
"params",
|
||||
"returnType",
|
||||
"body",
|
||||
"id",
|
||||
"generator",
|
||||
"start",
|
||||
"end",
|
||||
]);
|
||||
});
|
||||
Reference in new issue
Block a user