From f935d9434f9c83cf768f26d997bcb756f220da3b Mon Sep 17 00:00:00 2001 From: sapphi-red <49056869+sapphi-red@users.noreply.github.com> Date: Sat, 11 Jan 2025 07:23:07 +0000 Subject: [PATCH] feat(minifier): remove `new` from NativeErrors / `AggregateError` (#8430) Remove `new` in the some cases: - NativeErrors (e.g. `new EvalError(...)` -> `EvalError(...)`): [spec](https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-nativeerror-constructors:~:text=the%20function%20call%20NativeError(%E2%80%A6)%20is%20equivalent%20to%20the%20object%20creation%20expression%20new%20NativeError(%E2%80%A6)%20with%20the%20same%20arguments.), [the list of NativeErrors in spec](https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-native-error-types-used-in-this-standard) - `new AggregateError(...)` -> `AggregateError(...)`: [spec](https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-aggregate-error-constructor:~:text=the%20function%20call%20AggregateError(%E2%80%A6)%20is%20equivalent%20to%20the%20object%20creation%20expression%20new%20AggregateError(%E2%80%A6)%20with%20the%20same%20arguments.) --- .../peephole_substitute_alternate_syntax.rs | 32 +++++++++++++++++-- tasks/minsize/minsize.snap | 12 +++---- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs b/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs index 9a08e7b54ff77..8400d8aa4b6f4 100644 --- a/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs +++ b/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs @@ -979,7 +979,8 @@ impl<'a, 'b> PeepholeSubstituteAlternateSyntax { } } - /// `new Error()` -> `Error()` + /// `new Error()` -> `Error()` (also for NativeErrors) + /// `new AggregateError()` -> `AggregateError()` /// `new Function()` -> `Function()` /// `new RegExp()` -> `RegExp()` fn try_fold_new_expression( @@ -988,14 +989,17 @@ impl<'a, 'b> PeepholeSubstituteAlternateSyntax { ) -> Option> { let Expression::Identifier(ident) = &e.callee else { return None }; let name = ident.name.as_str(); - if !matches!(name, "Error" | "Function" | "RegExp") { + if !matches!(name, "Error" | "AggregateError" | "Function" | "RegExp") + && !Self::is_native_error_name(name) + { return None; } if !ctx.is_global_reference(ident) { return None; } if match name { - "Error" | "Function" => true, + "Error" | "AggregateError" | "Function" => true, + _ if Self::is_native_error_name(name) => true, "RegExp" => { let arguments_len = e.arguments.len(); arguments_len == 0 @@ -1019,6 +1023,21 @@ impl<'a, 'b> PeepholeSubstituteAlternateSyntax { } } + /// Whether the name matches any native error name. + /// + /// See for the list of native errors. + fn is_native_error_name(name: &str) -> bool { + matches!( + name, + "EvalError" + | "RangeError" + | "ReferenceError" + | "SyntaxError" + | "TypeError" + | "URIError" + ) + } + /// `typeof foo === 'number'` -> `typeof foo == 'number'` fn try_compress_type_of_equal_string(&mut self, e: &mut BinaryExpression<'a>) { let op = match e.operator { @@ -1419,6 +1438,13 @@ mod test { test("new Error('a')", "Error('a')"); test("new Error('a', { cause: b })", "Error('a', { cause: b })"); test_same("var Error; new Error()"); + test("new EvalError()", "EvalError()"); + test("new RangeError()", "RangeError()"); + test("new ReferenceError()", "ReferenceError()"); + test("new SyntaxError()", "SyntaxError()"); + test("new TypeError()", "TypeError()"); + test("new URIError()", "URIError()"); + test("new AggregateError()", "AggregateError()"); test("new Function()", "Function()"); test( diff --git a/tasks/minsize/minsize.snap b/tasks/minsize/minsize.snap index d8f80c668c751..843ed1dbec8f4 100644 --- a/tasks/minsize/minsize.snap +++ b/tasks/minsize/minsize.snap @@ -5,23 +5,23 @@ Original | minified | minified | gzip | gzip | Fixture 173.90 kB | 59.79 kB | 59.82 kB | 19.41 kB | 19.33 kB | moment.js -287.63 kB | 90.09 kB | 90.07 kB | 32.03 kB | 31.95 kB | jquery.js +287.63 kB | 90.08 kB | 90.07 kB | 32.03 kB | 31.95 kB | jquery.js 342.15 kB | 118.11 kB | 118.14 kB | 44.44 kB | 44.37 kB | vue.js 544.10 kB | 71.76 kB | 72.48 kB | 26.15 kB | 26.20 kB | lodash.js -555.77 kB | 273.21 kB | 270.13 kB | 90.93 kB | 90.80 kB | d3.js +555.77 kB | 273.16 kB | 270.13 kB | 90.92 kB | 90.80 kB | d3.js 1.01 MB | 460.18 kB | 458.89 kB | 126.77 kB | 126.71 kB | bundle.min.js -1.25 MB | 652.86 kB | 646.76 kB | 163.54 kB | 163.73 kB | three.js +1.25 MB | 652.84 kB | 646.76 kB | 163.54 kB | 163.73 kB | three.js -2.14 MB | 726.27 kB | 724.14 kB | 180.08 kB | 181.07 kB | victory.js +2.14 MB | 725.68 kB | 724.14 kB | 180.07 kB | 181.07 kB | victory.js 3.20 MB | 1.01 MB | 1.01 MB | 331.79 kB | 331.56 kB | echarts.js -6.69 MB | 2.32 MB | 2.31 MB | 492.64 kB | 488.28 kB | antd.js +6.69 MB | 2.32 MB | 2.31 MB | 492.63 kB | 488.28 kB | antd.js -10.95 MB | 3.49 MB | 3.49 MB | 907.45 kB | 915.50 kB | typescript.js +10.95 MB | 3.49 MB | 3.49 MB | 907.42 kB | 915.50 kB | typescript.js