Commit graph

7843 commits

Author SHA1 Message Date
Tapan Prakash
869bc73e67
fix(linter): enhance default_param_last rule to handle optional parameters (#8563)
- Enhanced default_param_last to handle optional parameters based on the
corresponding typescript-eslint rule.
- Added additional test cases from the typescript-eslint rule.

Closes https://github.com/oxc-project/oxc/issues/8556
2025-01-17 11:35:27 +00:00
Boshen
5cb9e979fe
feat(tasks/e2e): transformer + minifier runtime tests for popular npm packages (#8552)
Code extracted from
https://github.com/privatenumber/minification-benchmarks
2025-01-17 19:13:59 +08:00
sapphi-red
8f57929419
refactor(minifier): merge try_compress_type_of_equal_string into try_minimize_binary (#8561)
This compression can be handled by `try_minimize_binary`.
2025-01-17 11:01:54 +00:00
overlookmotel
007e8c017c refactor(ast, regular_expression): shorten ContentEq implementations (#8519)
Shorten codegen-ed implementations of `ContentEq` for enums, matching what Rust produces for `#[derive(PartialEq)]` (inspired by #8517).
2025-01-17 06:24:08 +00:00
overlookmotel
1d4c7a1099 ci(lint): run clippy in release mode (#8541)
CI Clippy task catch lint errors which only appear in release mode (e.g. the one fixed in #8539).

Add a profile for this. `cargo clippy --profile dev-no-debug-assertions` is about 35% faster than `cargo clippy --release` (and is slightly faster than plain `cargo clippy`) but catches the same problems.

This slows down the Clippy CI task, but it still remains faster than running conformance, so I don't think it's likely to slow down CI overall.
2025-01-17 06:14:35 +00:00
overlookmotel
72f425f074 refactor(transformer/class-properties): fix lint warning in release mode (#8539)
Fix a lint warning which only occurs in release mode.
2025-01-17 06:14:34 +00:00
sapphi-red
991a22f907
feat(minifier): fold Array::concat into literal (#8442)
Compress `[].concat(a, [b])` into `[a, b]`.

**References**
- [Spec of `Array::concat`](https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.concat)
2025-01-17 06:00:07 +00:00
sapphi-red
3dc2d8b8e9
feat(minifier): fold string concat chaining (#8441)
Compress `"".concat(a).concat(b)` into `"".concat(a, b)`.

**References**
- [Spec of `String::concat`](https://tc39.es/ecma262/multipage/text-processing.html#sec-string.prototype.concat)
2025-01-17 06:00:06 +00:00
Anson Heung
7ab14cc41c
feat(linter): add more Vitest compatible Jest rules (#8445)
There are many `eslint-plugin-vitest` rules that have an equivalent Rust
implementation for the Jest plugin. This PR ports all Jest rules that
passes the Vitest plugin's unit tests.

Some existing Jest rule implementations are not included in the
compatible list, for example:
- `no-large-snapshots` - difference in config initial values
- `no-mocks-import` - mention of the word "Jest" in diagnostics
- `prefer-called-with` - Vitest plugin implements a fix but Jest plugin
didn't
- `prefer-spy-on` - mention of the word "Jest" in diagnostics
- `prefer-to-contain` - the fix is missing
- `valid-title` - configuration options are slightly different

To get a list of already implemented Jest rules, simply run:
```bash
ls crates/oxc_linter/src/rules/jest | sed 's/\.rs$//;s/_/-/g'
```
2025-01-17 13:59:37 +08:00
sapphi-red
a4ae4505f1
feat(minifier): fold array concat chaining (#8440)
Compress `[].concat(a).concat(b)` into `[].concat(a, b)`.

**References**
- [Spec of `Array::concat`](https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.concat)

---

### The new assumption

I added a new assumption description in `crates/oxc_minifier/README.md`: "Errors thrown when creating a String or an Array that exceeds the maximum length can disappear or moved".
This is an assumption held by other minifiers. Without this assumption, we have to treat `+` and array creation/update to have a sideeffect and that limits the minification.

For input:
```js
[...Array(Number(2n ** 32n - 1n)),""]
" ".repeat(Number(2n ** 29n - 24n - 1n)) + ' '
export {}
```
(Note that `2 ** 32 - 1` is the max array length and `2 ** 29 - 24` is the max string length on V8.)
This code errors with too long array and too long string on V8 based runtimes.

terser outputs:
```js
Array(Number(2n**32n-1n))," ".repeat(Number(536870887n));export{};
```
No error will happen with this code.

SWC outputs:
```js
[...Array(Number(2n**32n-1n))]," ".repeat(Number(2n**29n-24n-1n));export{};
```
No error will happen with this code.
[playground](https://play.swc.rs/?version=1.10.7&code=H4sIAAAAAAAAA4vW09NzLCpKrNTwK81NSi3SMMpT0NJSMAZSugqGeZqaOkpKsbxcSgpKekWpBamJJajqjCxB6oxMYKoVtBXUFdR5uVIrCvKLShSqa3m5AGRqy%2FBiAAAA&config=H4sIAAAAAAAAA32UO3LjMAyG%2B5zCozrFjostcoDtcgYOTYIyvXxoCNCxJuO7L0RJtjeG3En48AMkAOL7bbfrTmi6j903f%2FLPoAtCuf2zBcdE%2BsKWDkzUaIofqHtf6Qkn5HRAaKbrTDrSpQdqKtz%2F2u8XRRdyRlgViy365N34mNPkOBRAfLCxlUPWCInwf%2F3CSv6aAJX6aD%2FkHECnF0RpVD4R9FCkwCaHoAcEddZFiDKdVBePWUoxwUpg1VDyIPJkPfmcOOcztaCtMtmCgHwBQ%2F4MkoxzsSwhX0%2B4T8MWDrXvW59%2FqOGsQ9Uk5IRLawmfVoh6zB5JuZqkEs5wowYzXIr7U%2BmdKkC1pGfdKfu00ZO%2FAFyBoBGTjiDFbR6O52lL7V4qfXI8sjQKnOdbumWCnouqvHdCZafKQCEvdbOArQamyhrpOAveKB96Cwqc41kRQuOXJ3OUktI4QHYC4P5qJ03VDNTtFW7w6UG8wH%2F4liQP2OIRNR23KY7xkMOLBBHomO0LB24F5W1ceEtchm1ekwUeDbCiS8UGnpcAPwDKKrR9%2BTQb%2FDw4oupDPtzXxOJwve3hqFN%2Ff%2B%2FzKn5bHLqYbW1wWfJTf%2BfV%2FLu7O61beD1B5%2FFzFbac13%2FKOhgeLwYAAA%3D%3D)

esbuild outputs:
```js
[...Array(Number(2n**32n-1n))]," ".repeat(Number(2n**29n-24n-1n))+"";export{};
```
No error will happen with this code.
[esbuild try](https://esbuild.github.io/try/#dAAwLjI0LjIALS1taW5pZnkAWy4uLkFycmF5KE51bWJlcigybiAqKiAzMm4gLSAxbikpLCIiXQoiICIucmVwZWF0KE51bWJlcigybiAqKiAyOW4gLSAyNG4gLSAxbikpICsgJyAnCmV4cG9ydCB7fQ)

OXC outputs:
```js
[...Array(Number(2n**32n-1n))]," ".repeat(Number(2n**29n-24n-1n))+" ";export{};
```
The array error won't happen and the String error will happen with this code.
[playground](https://playground.oxc.rs/#eNpVT71OwzAQfhXrlv4QIhpgIBtLR8SOGZxwCUH22To7baMo746dNEVMd5/u+7sRaijhI8/zV2Y1bN96UyFvCxL7vXiM414caLfLJEj4lCRBSMgZHarwn1u8JG7xtCrEndiIjSS8OMtBjJMkyMBCOQL3lIYfKKgLlIF7zEB3FKBslPYR+No6XC9+MJXVKwqsyDeWzZU8ZeAUe+TZ0vZc47HTSMpEAwjoQ/7jY7JjjKQTvitG8n/ilDuL437zXtyC4hZjKUBfPByeITJq+4UtpvoRmI66plu4tTUpIRovNc/fXcx2qr69YRS1+opmJwps9VHbc9KfkCvr43npNU2/v/WIsw==)
2025-01-17 05:53:54 +00:00
overlookmotel
d17021c834 perf(mangler): optimize base54 function (#8557)
Optimize mangler by creating identifiers in an inline array, instead of using the more expensive `CompactString`, and optimize `base54` function.

There's an unfortunate workaround necessary because of debug mode. In "normal" mode, identifiers are maximum 11 bytes (`usize::MAX` -> `ZrN6rN6rN6r`) but in debug mode they can be up to 25 bytes (`usize::MAX` -> `slot_18446744073709551615`). So this PR splits `build_with_symbols_and_scopes` into 2 branches for "normal" and "debug" modes with a generic function parameterized by max length of the string.

This is not ideal - it will increase binary size a bit, but everything else I tried (e.g. allocating strings into arena) was much slower.

The main motivation for this change wasn't actually performance. While working on allocator, I discovered that `CompactString`s were being allocated in arena (`reserved_names: ArenaVec<CompactStr>`), and wanted to remove them.
2025-01-17 05:47:28 +00:00
Yuji Sugiura
64d38b86b6
refactor(prettier): Verify printing class related nodes (#8559)
Part of #5068
2025-01-17 13:46:07 +08:00
overlookmotel
30a869ead2 perf(semantic): use oxc_allocator::HashMap in ScopeTree (#8554)
Use `oxc_allocator::HashMap` in `ScopeTree`, replacing `hashbrown::HashMap`. `oxc_allocator::HashMap` is non-drop, so it may reduce drop time of `ScopeTree` a little.
2025-01-16 23:29:58 +00:00
overlookmotel
bf4e5e1c18 feat(allocator): add HashMap (#8553)
Add `HashMap` type to `oxc_allocator`. `HashMap` is a thin wrapper around `hashbrown::HashMap`, which allocates in the arena. The inner map is wrapped in `ManuallyDrop`, so `HashMap` is non-`Drop` (same as `oxc_allocator::Vec`).

We use `FxHasher` for all hash maps, so I figured just make that part of the type, rather than having to specify the hasher everywhere we use `HashMap`.
2025-01-16 23:29:57 +00:00
overlookmotel
fa1a6d5ede docs(allocator): update docs for Vec (#8555)
Remove line from `oxc_allocator::Vec` docs saying "Should only be used for storing AST types.". We are now using `Vec` in `Semantic` too, and there's no problem with that.
2025-01-16 19:18:16 +00:00
overlookmotel
a04833787d fix(transformer/class-static-blocks): static block converted to IIFE use span of original block (#8549)
Fix spans in class static blocks and class properties transforms. When a static block is converted to an IIFE, the IIFE should take the span of the static block.
2025-01-16 14:55:53 +00:00
overlookmotel
712633f0bc refactor(transformer): wrap_statements_in_arrow_function_iife utility function (#8548)
Move utility function for creating an IIFE from `ClassStaticBlock` transform to utils module.
2025-01-16 14:55:52 +00:00
overlookmotel
b552f5cfd3 fix(transformer): wrap_in_arrow_function_iife take span of input Expression (#8547)
#8530 introduced a small change. Previously the IIFE had the span of the original expression which is being wrapped, but after that PR it got a dummy `SPAN`. Fix that.
2025-01-16 14:55:51 +00:00
overlookmotel
5206c6ae06 refactor(transformer): rename wrap_in_arrow_function_iife (#8546)
Pure refactor. Rename this function to be more descriptive.
2025-01-16 14:55:51 +00:00
overlookmotel
61077cae9f refactor(transformer): wrap_arrow_function_iife receive an owned Expression (#8545)
Follow-on after #8529. Pure refactor. `wrap_arrow_function_iife` receive an owned `Expression`, instead of `&mut Expression`.

This does require a bit more repeated code in the caller, but still I think it's more appropriate for a utility function. If we use it again elsewhere, it's non-obvious if it replaces the input `&mut Expression` with a `NullLiteral` via `move_expression`. Better to leave that to the caller.
2025-01-16 14:55:50 +00:00
camc314
65c596d002 fix(minifer): keep idents if not in scope when minimizing array exprs (#8551) 2025-01-16 14:26:37 +00:00
camc314
7cc81ef5ef feat(minifier): fold invalid typeof comparisons (#8550) 2025-01-16 14:26:36 +00:00
Boshen
c479a58718
feat(napi/parser): expose dynamic import expressions (#8540)
closes #8369
2025-01-16 22:25:22 +08:00
camc314
f57aac2aee fix(minifier): incorrect folding of expr in bool ctx (#8542)
esbuild code comment is wrong.

8f1faf7d4a/internal/js_ast/js_ast_helpers.go (L2127-L2128)

https://esbuild.github.io/try/#dAAwLjI0LjIALS1taW5pZnkAaWYgKGFueXRoaW5nMSA/ICgwLCBmYWxzZSkgOiBhbnl0aGluZzIpOw
2025-01-16 14:18:03 +00:00
Dunqing
c30654a793 refactor(transformer/arrow-function): wrapping arrow function iife by using wrap_arrow_function_iife (#8530) 2025-01-16 12:49:28 +00:00
Dunqing
6820d24c4a refactor(transformer): move wrap_arrow_function_iife to root utils module (#8529) 2025-01-16 12:42:14 +00:00
Dunqing
f413bb5c64 feat(transformer/optional-chaining): change parent scope for expression when it wrapped with an arrow function (#8511) 2025-01-16 12:21:44 +00:00
overlookmotel
8dd0013e72 refactor(linter/consistent-function-scoping): remove Visit::enter_node usage (#8538)
Use `Visit::visit_*` method instead of `Visit::enter_node` / `leave_node`. A step towards solving #8461, but also may improve performance.
2025-01-16 11:00:11 +00:00
overlookmotel
30c0689dfc refactor(linter/no-map-spread): remove Visit::enter_node usage (#8537)
Use `Visit::visit_*` method instead of `Visit::enter_node` / `leave_node`. A step towards solving #8461, but also may improve performance.
2025-01-16 10:55:16 +00:00
Alexander S.
b4c87e27a1
refactor(linter): move DiagnosticsReporters to oxlint (#8454)
it was never the plan that oxc_diagnostics should be the
`std::io::stdout` writer:

8fc238ac34/crates/oxc_diagnostics/src/service.rs (L84-L85)

This PR does refactor all reporters to `oxlint` crate and make the
current implementation of `oxc_diagnostics` public for others to
consume.

I added some tests to reflect to expected output (and found some bugs^^)

For the future I think the BufWriter for `std::io::stdout` should come
from outside.
Or maybe `std::fmt::stdout`? I do not know^^"

I could not test 100% of the code, I hope I can fix this with the next
PR which will include a own Tester for oxlint (like `oxc_linter`).
Please be extra careful when reviewing it.

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2025-01-16 16:11:22 +08:00
Boshen
9ec4e24eb7
test(napi/minify): fix more broken tests 2025-01-16 16:09:23 +08:00
Boshen
0acbef356a
test(napi/minify): fix matching of arrays 2025-01-16 15:34:20 +08:00
Boshen
855c8395cf fix(codegen): shorthand assignment target identifier consider mangled names (#8536) 2025-01-16 07:26:07 +00:00
Boshen
946ad7690b fix(minifier): (-Infinity).toString() -> '-Infinity' (#8535) 2025-01-16 06:47:40 +00:00
Boshen
e0f5d6c7bb
test(minifier): update esbuild test 2025-01-16 14:46:12 +08:00
Boshen
927f43ff84 feat(minifier): improve .charCodeAt(arg) when arg is valid (#8534) 2025-01-16 06:36:34 +00:00
Boshen
b1d018622b fix(minifier): do not fold !!void b (#8533) 2025-01-16 05:52:03 +00:00
Dunqing
f5c5c3c9f1 chore(coverage/runtime): skip tests which are eval in class (#8532)
These tests need performing `eval`, we cannot support them. @overlookmotel and I have agreed to ignore them to reduce the noise.
2025-01-16 05:44:32 +00:00
Boshen
53adde5003
fix(minifier): x['-2147483648'] -> x[-2147483648] (#8528) 2025-01-16 13:43:23 +08:00
Boshen
405b73d8e7 fix(minifier): do not change delete undefined to delete void 0 (#8527)
`delete undefined` returns `false`
`delete void 0` returns `true`
2025-01-16 03:08:26 +00:00
Boshen
92e44cba6b fix(minifier): do not remove undefined in var x = undefined (#8526) 2025-01-16 02:57:28 +00:00
Boshen
06f14d526b feat(minifier): remove empty class static block class Foo { static {} } (#8525) 2025-01-16 02:46:25 +00:00
overlookmotel
2857ae15cd refactor(parser): refactor visitor in regexp example (#8524)
Refactor visitor in example to use `visit_*` methods instead of `enter_node`. This is our recommended style as it's more performant.
2025-01-16 02:40:29 +00:00
Boshen
1860411656 feat(minifier): remove last redundant return statement (#8523) 2025-01-16 02:07:28 +00:00
Valentinas Janeiko
4ce63298e8
fix(semantic)!: ensure program outlives semantic (#8455)
fixes: #8437 

In semantic builder make sure `Program` reference has a lifetime of the
Arena.

---------

Co-authored-by: overlookmotel <theoverlookmotel@gmail.com>
2025-01-16 10:04:25 +08:00
overlookmotel
250bbd193b perf(linter/react-exhaustive-deps): use stack of AstTypes instead of AstKinds (#8522)
This lint rule keeps a stack tracing the "visitation path" during `Visit`. Only the type of the nodes is used, not their values, so store only `AstType` (1 byte) rather than `AstKind` (16 bytes).

This should be more performant, but the main motivation is #8461. This is one of very few places in the codebase which uses `enter_node` and `leave_node`. Not storing `AstKind`s here clears the way to remove the unsound lifetime extension in `Visit::alloc`.
2025-01-16 00:32:38 +00:00
overlookmotel
a6d71f8f27 feat(ast): add AstKind::ty method (#8521)
Add `AstKind::ty` method to get `AstType` from an `AstKind`.

Works by setting the enum discriminants of `AstKind` and `AstType` to be the same, so one can be converted to the other at zero cost.
2025-01-16 00:32:37 +00:00
Dunqing
06ccb51fae fix(transformer/async-to-generator): move parameters to the inner generator function when they could throw errors (#8500)
The new implementation port from [esbuild](df815ac27b/internal/js_parser/js_parser_lower.go (L355-L467)), before from `Babel`.

Babel's transform implementation for the async method is incorrect because the async method should return a rejecting promise when it throws an error. Everything is good if the errors are thrown in the async method body, but the following case will throw an error in the parameters which causes the whole program crushed not a rejecting promise. So we should move the parameters to the inner generator function when the parameters could throw an error.

Input:
```js
class Cls {
  // ReferenceError: Cannot access 'b' before initialization
  async method(a = b, b = 0) {}
}
```

Before output
```js
class Cls {
  method(a = b, b = 0) {
    return babelHelpers.asyncToGenerator(function* () {})();
  }
}
```

After output:
```js
class Cls {
  method() {
     // ReferenceError: Cannot access 'b' before initialization
    return babelHelpers.asyncToGenerator(function* (a = b, b = 0) {}).apply(this, arguments);
  }
}
```

No override tests because Babel doesn't cover this case.
2025-01-16 00:18:05 +00:00
overlookmotel
3789d2faf9 style(linter/react-exhaustive-deps): fix indentation (#8520) 2025-01-15 23:46:38 +00:00
Dunqing
52bd0b1004 refactor(transformer): move common utils functions to the root module (#8513)
These utils functions are very useful for other plugins, I am going to gradually move utils functions where in separate plugins into the root utils module. It also will include scope adjusting functions.
2025-01-15 20:41:09 +00:00