Add an AST visitor to `oxc-parser`.
```js
import { parseSync, Visitor } from 'oxc-parser';
const { program } = parseSync('test.js', 'let x = { y: z };');
const idents = [];
const visitor = new Visitor({
Identifier(node) {
idents.push(node.name);
}
});
visitor.visit(program);
// Logs [ 'x', 'y', 'z' ]
console.log(idents);
```
Primarily we need a visitor for Oxlint plugins, but it's easier to develop and test in `oxc-parser`, so I thought I'd add it there first. Oxlint build process will copy the generated files for tree-walking from `napi/parser` dir, as it does with other files.
Notes:
* The `walk.mjs` file is large, so it's lazy-loaded only when user first constructs a `Visitor`. Adding `Visitor` to the package will not affect start-up time where user only uses `parseSync` etc.
* TS type definition for `Visitor` and the visitor object it takes are provided.
* Visitor supports enter and exit visitors e.g. `Program` and `Program:exit`.
* `src-js/visit/visitor.mjs` is copied from `apps/oxlint` with only minor modifications, and conversion from TS to JS. It'd be better if we only had this impl in one place, but that would require converting `oxc-parser` to TS and building with TSDown, like `oxlint` is. Leaving that for later - #13935.
Add visitor keys export to `oxc-parser` NPM package. This is useful in itself, but also the first step towards an ESTree walker.
Visitor keys are based on `@typescript-eslint/visitor-keys`.
It'd be ideal to generate visitor keys direct from Oxc's own types, but that's proving difficult due to all the custom serializers we use to translate to ESTree. So using the shortcut of borrowing from TS-ESLint for now.
Oxc's AST is slightly different from TS-ESTree (notably Oxc's AST adds `ParenthesizedExpression`). But apart from those few differences, TS-ESLint's AST and Oxc's are identical, and I made a PR to TS-ESLint earlier this year (https://github.com/typescript-eslint/typescript-eslint/pull/11279) to ensure visitor key order is correct, and matches Oxc.
To avoid adding a runtime dependency on `@typescript-eslint/visitor-keys`, extract the data from TS-ESLint in `oxc_ast_tools`, amend for Oxc/TS-ESTree differences, and re-output it as a simple object literal.
This approach will be faster at runtime, as the object's shape is consistent, and also avoids a dependency.
#13899 made the `files` array in `package.json` for `napi/parser` package a short list of directories. Revert to an itemized list of all files to be included in NPM package.
This is for compatibility with the release workflow which checks the list of files in `package.json` against file system. It fails when `files` list contains directories.
Pure refactor. Root of `napi/parser` was getting really crowded with tons of files, and I'm about to add a load more for the ESTree walker.
Move JS source files into a `src-js` directory, like in `apps/oxlint`, so that the root of the package is just config files and scripts.
In https://github.com/oxc-project/oxc/pull/13432 the filename was
changed but `main` remained as is. I'm now seeing following error in
Vitest:
```
⎯⎯⎯⎯⎯⎯ Unhandled Error ⎯⎯⎯⎯⎯⎯⎯
Error: Failed to resolve entry for package "oxc-parser". The package may have incorrect main/module/exports specified in its package.json.
1 | import { parse as BabelParser } from "@babel/parser";
2 | import { parse as AcornParser } from "acorn";
3 | import { parseSync as OxcParser } from "oxc-parser";
| ^
4 | import { parseAst as ViteParser } from "vite";
5 | import { expectTypeOf, test } from "vitest";
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
```
https://github.com/AriPerkkio/ast-v8-to-istanbul/actions/runs/17722503037/job/50357275013?pr=86
See errors from https://publint.dev/oxc-parser@0.88.0.
Signed-off-by: Ari Perkkiö <ari.perkkio@gmail.com>
Compile NAPI tests in debug mode (not release mode), to speed up build in CI.
Only exception is `napi/parser` which is compiled with `--profile coverage`. The tests for this package are quite slow, so they'd take too long if package was compiled with no optimizations. `coverage` profile is closer to `--release`, but enables debug assertions, and has somewhat faster compilation (`-O 2` not `-O 3` etc).
In CI:
* Build time reduced by 1m30s.
* Test run time increased by 30s.
* Total reduction in CI time: 1 minute.
NAPI tests are still the slowest task in CI by a long margin. Trimming a minute off the time is something, but this task is still too slow.
Pure refactor. Instead of hard-coding constants for fixed offsets of data in the buffer, generate these constants in one place and import them from `constants.js` everywhere else.
Add lazy visitor to `oxc-parser`.
This API is experimental and not ready for use yet. AST is not ESTree-compatible at present (same as lazy deserializer).
Usage:
```js
import { parseSync, experimentalGetLazyVisitor } from 'oxc-parser';
// Get `Visitor` class.
// `Visitor` is not exported directly from `oxc-parser` as all code
// related to lazy deserialization is lazy-loaded.
const Visitor = experimentalGetLazyVisitor();
// Define visitor.
// This visitor counts how many identifiers in AST.
let identCount = 0;
const visitor = new Visitor({
BindingIdentifier(ident) {
identCount++;
},
IdentifierReference(ident) {
identCount++;
},
IdentifierName(ident) {
identCount++;
},
});
const code = 'let x, y; x = { z: 2 };';
const { visit, dispose } = parseSync('test.js', code, { experimentalLazy: true });
visit(visitor);
assert(identCount === 4);
// Dispose of AST now we're done with it.
// This returns buffer storing AST data to the pool for reuse.
dispose();
```
Raw transfer and raw lazy deserialization are experimental and not publicly advertised. Lazy-load all code for these features only when they're first used.
Lazy deserialization in particular requires a non-trivial amount of code.
`rawTransferSupported` still needs to be eagerly loaded, as user would call it before calling `parseSync` or `parseAsync`. So move it into a separate module.