This PR makes 2 changes to improve the existing API that are not very useful.
- Remove `(Literal)Parser` and `FlagsParser` and their ASTs
- Add `with_flags(flags_text)` helper to `ParserOptions`
Here are the details.
> Remove `(Literal)Parser` and `FlagsParser` and their ASTs
Previously, the `oxc_regular_expression` crate exposed 3 parsers.
- `(Literal)Parser`: assumes `/pattern/flags` format
- `PatternParser`: assumes `pattern` part only
- `FlagsParser`: assumes `flags` part only
However, it turns out that in actual usecases, only the `PatternParser` is actually sufficient, as the pattern and flags are validated and sliced in advance on the `oxc_parser` side.
The current usecase for `(Literal)Parser` is mostly for internal testing.
There were also some misuses of `(Literal)Parser` that restore `format!("/{pattern}/{flags}")` back and use `(Literal)Parser`.
Therefore, only `PatternParser` is now published, and unnecessary ASTs have been removed.
(This also obsoletes #5592 .)
> Added `with_flags(flags_text)` helper to `ParserOptions`
Strictly speaking, there was a subtle difference between the "flag" strings that users were aware of and the "mode" recognised by the parser.
Therefore, it was a common mistake to forget to enable `unicode_mode` when using the `v` flag.
With this helper, crate users no longer need to distinguish between flags and modes.
- fixes https://github.com/oxc-project/oxc/issues/5913
This PR fixes the calculation of spans when dealing with files that have multiple sources and non-zero source start offsets. This is almost always the case for `.vue`, `.astro`, and `.svelte` files. This enables us to correctly apply fixes for these file types both in the CLI with `oxlint` and also in editors like VS Code.
https://github.com/user-attachments/assets/2836c8bd-09be-4e59-801d-7c95f8c2491f
I'm open to ideas on how to improve testing in this area, as I don't think that we currently have any tests for fixing files end-to-end (beyond what the linter rules check). I did run this locally on the gitlab repository (which is written in Vue) and all of the fixes appeared to be applied correctly.
```rs
test("x = ~2147483658.0", "x = 2147483637");
test("x = ~-2147483658", "x = -2147483639");
```
Used `wrapping_neg`, and maybe it is a great solution for #6161.
In common transforms, move all functionality into the `*Store` structs. The `Traverse` impls become just thin wrappers which call into methods on the `*Store` structs.
I think this is clearer because now reading these files from top-to-bottom, you have the code that inserts into the stores before the code that reads from the stores and acts on it.
Minifier benchmark currently includes the time to run parser and semantic as well as the minifier itself. Similar to transformer benchmark, only measure the minifier itself in the benchmark.
This will give us a clearer picture of performance changes, and should also reduce variance in the benchmarks.
`ReplaceGlobalDefines` was putting a `String` into the arena. `String` allocates on the heap, so this was a memory leak because it didn't get dropped when the allocator is dropped. This was caught by Miri.
Allocate a string slice instead.
Remove `SparseStack::is_empty` method. It's pointless as the stack is never empty.
Add a dummy `NonEmptyStack::is_empty` method that always returns `false`. This is also pointless, but it overrides `slice::is_empty` which is otherwise accessible via `Deref`.
`impl<'alloc, T> ops::Index<usize> for &'alloc Vec<'alloc, T>` is unnecessary, as we already have `impl<'alloc, T> ops::Index<usize> for Vec<'alloc, T>`, whose `index` method takes a `&self`.
Both React and TypeScript transforms were repeating the same work - iterating through comments to find `@jsx` pragmas.
Instead, perform this search only once, using the optimized pragma search introduced in #6151.
We don't need to store `ImportKind` for every import in `ModuleImports`. Whether we generate `import`s or `require`s depends on the source type (module or script), which is a global setting.
Fix a tiny bug in `add_require`. If `front` option is `true` but there's already an entry for the key, it may not be the last entry in the index map, so `move_index(len, 0)` could swap a *different* `require` to be first.
This will not make a difference in practice right now as we don't add enough `requires` at present for it to matter. But it might do once we add imports of helpers etc.
An alternative version of #6177.
Convert `ModuleImports` into a common transform. Works much as before, but it inserts `import` / `require` statements by passing them to `TopLevelStatements` common transform, so they get inserted in one go with any other inserted top-level statements. This avoids shuffling up the `Vec<Statement>` multiple times, which can be slow with large files.
`VarDeclarations` also inserts any declarations via `TopLevelStatements` but runs after `ModuleImports`, so can control whether a `var` statement is inserted before or after `import` statements by inserting it via `VarDeclarations` (to appear after `import` statements) or directly into `TopLevelStatements` (to appear before `import` statements). Insertion order is not actually important, but allows us to match Babel's output and pass its tests.
Introduce `TopLevelStatements` common transform. It holds a `Vec` of statements to be inserted at the top of the program, and other transforms can push statements to it.
All statements will be inserted in one go at the end of traversal, to avoid shuffling up the `Vec<Statement>` multiple times, which can be slow with large files.
resolves#6201.
It is uncertain whether this applies to other situations, so let us eliminate it in negation first, and after I have conducted a comprehensive investigation of the Closure Compiler, we can make a definitive decision.