Now that `apps/oxlint` and `napi/parser` are both ESM packages (#13723 and #14042), we can use `.js` file extensions for all ESM files, rather than the mix of `.js` and `.mjs` file we had previously.
It's less confusing having to remember what's `.js` and what's `.mjs`, and avoids ugly workarounds like #14038 (`.d.mts`??).
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.
Same as #13184.
#13173 enabled Oxlint for all the repo, but we currently skip `napi` directory.
Fix all errors that Oxlint flags in `napi/parser`.
We currently can't turn on Oxlint for the directory, because `oxlint-disable` comments don't work for type-aware rules, but we should be able to once that's fixed.
Integers `>= 4294967295` are treated as string properties, not numerical array indexes. Make `NodeArray` behave the same as `Array` for such properties, and allow user to set them.
`NodeArray` store length as an internal property, rather then creating an underlying `Array` with that length. This is much faster when the array is large.
Produces an 18x speed-up in getting `program.body` for `cal.com.tsx` benchmark fixture, because it has 3942 statements.
Implement an optimized `slice` method for `NodeArray` in lazy-deserialized AST. It returns a another `NodeArray`, instead of a plain `Array`, and doesn't deserialize any of the contents.
Lazy deserialization return `NodeArray`s which deserialize their contents lazily, instead of plain JS arrays.
`program.body.find(stmt => stmt.type === 'ImportDeclaration')` now only deserializes the nodes up until first `ImportDeclaration`, rather than deserializing every statement in the program into an array, and then searching it. Similarly getting `program.body.length` does not deserialize any nodes, and all other array methods are similarly optimized.
Also provide an optimized iterator for the common case of:
```js
for (const stmt of program.body) {
doStuff(stmt);
}
```
In lazy-deserialized AST, cache node objects, so accessing the same field twice returns the same object. Previously `assert(binaryExpression.left == binaryExpression.left)` would fail, as each access returned a new object.
`pos` (i.e. memory address) is used as the cache key, with 2 exceptions: `RegExp` and `Program`.
`RegExp` doesn't have a `span: Span` field, so its first field `RegExpPattern` has the same memory address as the `RegExp`. So `pos` would not be a unique key.
```rs
pub struct RegExp<'a> {
pub pattern: RegExpPattern<'a>,
pub flags: RegExpFlags,
}
pub struct RegExpPattern<'a> {
pub text: Atom<'a>,
pub pattern: Option<Box<'a, Pattern<'a>>>,
}
```
The codegen identifies these cases, and applies a workaround - `pos + 1` is used as the cache key instead of `pos`, so the parent and child have different cache keys.