Commit graph

191 commits

Author SHA1 Message Date
sapphi-red
8d52cd0a5e
feat(minifier): merge assign expression in conditional expression (#8345)
compresses `a ? b = 0 : b = 1` into `b = a ? 0 : 1`

This can be done when `b` is an IdentifierReference and the assignment operator is `=`.

In this circumstance, the evaluation of `b = a ? 0 : 1` is:

1. Let lref be ? Evaluation of LeftHandSideExpression. (this does not have a side effect when LeftHandSideExpression is an IdentifierReference)
2. Let rref be ? Evaluation of AssignmentExpression. (ConditionalExpression is evaluated here)
3. Let rval be ? GetValue(rref).
4. Perform ? PutValue(lref, rval).
5. Return rval.

**References**
- [spec of `=`](https://262.ecma-international.org/15.0/index.html#sec-assignment-operators-runtime-semantics-evaluation)
- [spec of `? :`](https://262.ecma-international.org/15.0/index.html#sec-conditional-operator-runtime-semantics-evaluation)
2025-01-08 13:34:12 +00:00
sapphi-red
a69d15f299
feat(minifier): compress new Array(2) -> [,,] (#8344)
For an integer value `n` smaller than 6, `Array(n)` can be compressed to `[,,]` (the number of `,` is `n`).
2025-01-08 12:07:46 +00:00
Boshen
6220e05f38 feat(minifier): remove empty if statment if (test) {} -> test (#8336) 2025-01-08 08:50:10 +00:00
sapphi-red
ec88c68c28
feat(minifier): compress a || (a = b) to a ||= b (#8315)
Compress `a || (a = b)` to `a ||= b` and for other logical operators that are possible to.

I didn't find other minifiers doing this, but this is safe for identifiers. [Quoting MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_OR_assignment#description):

> Logical OR assignment short-circuits, meaning that `x ||= y` is equivalent to `x || (x = y)`, except that the expression x is only evaluated once.

I actually checked the spec and the only difference was that `Let lRef be ? Evaluation of LeftHandSideExpression` was done twice. Evaluating an IdentifierReference is idempotent so it should be safe to do this compression.

References:

- [Spec of `&&=`](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-assignment-operators:~:text=Return%20r.-,AssignmentExpression,7.%20Return%20rVal.,-AssignmentExpression)
- [Spec of `=`](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#prod-AssignmentExpression:~:text=Runtime%20Semantics%3A%20Evaluation-,AssignmentExpression,6.%20Return%20rVal.,-AssignmentExpression)
- [Spec of `&&`](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-binary-logical-operators:~:text=Runtime%20Semantics%3A%20Evaluation-,LogicalANDExpression,5.%20Return%20%3F%C2%A0GetValue(rRef).,-LogicalORExpression)

I think this is safe for `a.b || (a.b = foo)` as well because the number of `GetValue` and `SetValue` does not change, but I didn't include that in this PR.
2025-01-07 23:19:52 +00:00
sapphi-red
e6fe84d674
feat(minifier): compress a = a + b to a += b (#8314)
Compress `a = a + b` to `a += b` and for other binary operators that are possible to.
2025-01-07 23:19:50 +00:00
sapphi-red
9ea4e31ba3
feat(minifier): remove new from new Error/new Function/new RegExp (#8313)
Remove `new` from some cases:

- `new Error(...)` -> `Error(...)`: `new` can be removed unconditionally, [spec](https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-error-constructor:~:text=Thus%20the%20function%20call%20Error(%E2%80%A6)%20is%20equivalent%20to%20the%20object%20creation%20expression%20new%20Error(%E2%80%A6)%20with%20the%20same%20arguments.)
- `new Function(...)` -> `Function(...)`: `new` can be removed unconditionally, [spec](https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-function-constructor:~:text=Thus%20the%20function%20call%20Function(%E2%80%A6)%20is%20equivalent%20to%20the%20object%20creation%20expression%20new%20Function(%E2%80%A6)%20with%20the%20same%20arguments.)
- `new RegExp(nonRegexp)` -> `RegExp(nonRegexp)`: `new` can be removed if there's no argument or the first argument is not regex object, [mdn](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/RegExp#return_value), [spec](https://tc39.es/ecma262/multipage/text-processing.html#sec-regexp-constructor:~:text=when%20called%20as%20a%20function%20rather%20than%20as%20a%20constructor%2C%20returns%20either%20a%20new%20RegExp%20object%2C%20or%20the%20argument%20itself%20if%20the%20only%20argument%20is%20a%20RegExp%20object.). I made this to happen if the first argument is not an object.
2025-01-07 14:48:56 +00:00
Boshen
051fbb6909 feat(minifier): minimize x["0"] -> x[0] (#8316) 2025-01-07 13:12:35 +00:00
Boshen
a542013773 feat(minifier): minimize do{}while(true) -> do;while(true) (#8311) 2025-01-07 12:55:03 +00:00
Boshen
e3ff81ef82 feat(minifier): minimize (x = 1) === 1 -> (x = 1) == 1 (#8310) 2025-01-07 07:48:35 +00:00
camc314
5ed439bcaf feat(minifier): minify typeof in binary expressions (#8302) 2025-01-06 23:26:19 +00:00
Boshen
b8d26eab17 refactor(minifier): move optional catch param to peephole_substitute_alternate_syntax (#8282) 2025-01-06 10:47:56 +00:00
Boshen
f87da160df fix(minifier): do not fold literals in -0 != +0 (#8278) 2025-01-06 10:08:57 +00:00
camc314
e446c15619 feat(minifier): improve minimizing unary not expressions (#8261) 2025-01-06 02:21:26 +00:00
camc314
7f19211736 feat(minifier): minimize unary expression statements (#8256)
`delete` cannot be minified as it may have side effect.
2025-01-06 02:21:24 +00:00
Boshen
4d8a08d2ac feat(minifier): improve constant evaluation (#8252) 2025-01-05 12:41:57 +00:00
Boshen
2f52f333fa feat(minifier): minsize !!!foo ? bar : baz -> foo ? baz : bar (#8244) 2025-01-04 09:10:22 +00:00
Boshen
ce2b5a994b chore(minifier): disable RemoveUnusedCode (#8243)
A lot of edge cases fail in test262 and monitor-oxc.
2025-01-04 08:49:20 +00:00
Boshen
ad9a0a9c4a feat(mininifier): minimize variants of a instanceof b == true (#8241) 2025-01-04 06:04:52 +00:00
Boshen
ccdc039f54 feat(minifier): always put literals on the rhs of equal op 1==x => x==1 (#8240) 2025-01-04 04:07:54 +00:00
Boshen
bf0fbcea6e refactor(minifier): improve constant fold numbers (#8239)
Ported esbuild's implementation
2025-01-04 03:30:20 +00:00
Cameron
39353b22e9
feat(minifier): improve minimizing conditionals (#8238) 2025-01-04 08:36:54 +08:00
camc314
c90fc16bba feat(minifier): restore conditional minification and fix edge case (#8235)
This restore's the changes made in #8233, but fixing the edge cases.

If the conditional expression is not a child of an `IfStatementTest`, `WhileStatementTest`, `DoWhileStatementText` or `ExpressionStatementExpression`, we must coerce the test to a boolean.
2025-01-03 14:20:42 +00:00
Boshen
6c8ee9fdef feat(minifier): remove last redundant return statement (#8234) 2025-01-03 12:24:57 +00:00
Boshen
a698deff51 fix(minifier): fix incorrect return value for (x ? true : y) (#8233)
Need to check if the return value is used or not:

```
function foo() {
    return foo ? true : bar; // no transformed
}

foo ? true : bar; // transformed to `foo || bar;`
```
2025-01-03 11:58:28 +00:00
Boshen
51f47926ef feat(minifier): minimize foo ? foo : bar and foo ? bar : foo (#8229) 2025-01-03 10:55:59 +00:00
Boshen
6e2ec17d51 feat(minifier): statement fusion switch cases; improved minimize exit poitns (#8228) 2025-01-03 10:07:04 +00:00
Boshen
574a2428fd feat(minifier): minimize all variants of typeof x == 'undefined' (#8227) 2025-01-03 07:05:55 +00:00
Boshen
2041477f51 feat(minifier): fold if(x)return;y -> if(!x)y (#8226) 2025-01-03 05:24:53 +00:00
Boshen
9c1afa4729 feat(minifier): optional catch binding when catch param is unused (#8221) 2025-01-02 13:20:49 +00:00
Boshen
2786dea164 feat(minifier): add RemoveUnusedCode (#8210) 2025-01-02 12:50:21 +00:00
Cameron
cd274eeb02
feat(minifier): minimize logical exprs (#8209) 2025-01-02 18:32:20 +08:00
Boshen
05be1fc639 fix(minifier): remove incorrect fold Expression::AssignmentExpression (#8211) 2025-01-01 05:44:01 +00:00
camc314
4ae15df042 feat(minifier): imprve more conditional expr minification with boolean lit (#8208) 2025-01-01 02:31:18 +00:00
camc314
3202b4fed0 feat(minifier): imprve conditional expr minification with boolean lit (#8207) 2025-01-01 02:31:18 +00:00
camc314
3b4501183c feat(minifier): handle conditional expr with boolean lit (#8206) 2025-01-01 02:31:17 +00:00
camc314
4c2059af29 feat(minifier): reverse negated conditional exprs (#8205) 2025-01-01 02:31:17 +00:00
Cameron
bf266e13b0
feat(minifier): try collapse conditional to logical or expr (#8197) 2024-12-31 15:59:08 +08:00
Boshen
06e1780b8c feat(minifier): improve StatementFusion (#8194) 2024-12-31 01:13:24 +00:00
Boshen
42e211ad6b feat(minifier): only constant fold numbers when result is smaller (#8092) 2024-12-31 00:56:51 +00:00
翠 / green
cef8eb8077
feat(minifier): change foo?.['bar'] to foo?.bar (#8176)
ChainExpression's `expression` field is `ChainElement` and not
`Expression` so the previous code did not run for optional chainings.
2024-12-30 16:47:56 +08:00
Boshen
cfb51f2551 refactor(minifier): fuse ast passes (#8184) 2024-12-29 14:57:20 +00:00
Boshen
8149e34bf0 feat(minifier): optional catch binding when es target >= es2019 (#8180) 2024-12-29 12:27:33 +00:00
Boshen
ad146bbb90 feat(codegen): print real newline when \n is inside template literals (#8178) 2024-12-29 12:20:47 +00:00
sapphi-red
75d5f17dbd
fix(minifier): minify string PropertyKey (#8177)
#8169 added `if self.in_fixed_loop` in `try_compress_property_key`. Because `exit_property_key` was not called for `PeepholeOptimizations`, `try_compress_property_key` was never called.

refs #8147
2024-12-29 07:49:42 +00:00
sapphi-red
fc43ec530e
feat(minifier): fold string.length / array.length (#8172) 2024-12-29 07:14:13 +00:00
Boshen
29dc0dc070 feat(minifier): change foo['bar'] -> foo.bar (#8169) 2024-12-29 04:09:42 +00:00
翠 / green
3c5718d68b
feat(minifier): fold typeof foo == undefined into foo == undefined when possible (#8160) 2024-12-29 11:49:57 +08:00
翠 / green
9d62284202
chore(tasks): print diff for minify idempotency assertion (#8161)
Made the assertion error output more easier to understand.

Example output:

![image](https://github.com/user-attachments/assets/445910fb-b389-4884-b4c5-70a095bc523f)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2024-12-29 00:55:45 +08:00
翠 / green
f3a36e1dbf
feat(minifier): fold typeof foo != "undefined" into typeof foo < "u" (#8159) 2024-12-29 00:50:56 +08:00
Boshen
37c9959611 feat(minifier): normalize Infinity into f64::Infinity (#8148) 2024-12-28 06:05:04 +00:00