Skip to content

Commit

Permalink
feat(minifier): drop 0 from new Int8Array(0) and other TypedArrays (
Browse files Browse the repository at this point in the history
#8431)

Compresses `new Int8Array(0)` into `new Int8Array()`. (then will be compress into `new Int8Array`).

Partial quote from the [spec](https://tc39.es/ecma262/multipage/indexed-collections.html#sec-typedarray):

> 5. If numberOfArgs = 0, then
>   a. Return ? AllocateTypedArray(constructorName, NewTarget, proto, 0).
> 6. Else,
>   c. Else,
>       ii. Let elementLength be ? ToIndex(firstArgument).
>      iii. Return ? AllocateTypedArray(constructorName, NewTarget, proto, elementLength).
  • Loading branch information
sapphi-red committed Jan 11, 2025
1 parent f935d94 commit d56020b
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ impl<'a> Traverse<'a> for PeepholeSubstituteAlternateSyntax {
self.try_compress_normal_assignment_to_combined_assignment(e, ctx);
self.try_compress_normal_assignment_to_combined_logical_assignment(e, ctx);
}
Expression::NewExpression(e) => {
self.try_compress_typed_array_constructor(e, ctx);
}
_ => {}
}

Expand Down Expand Up @@ -1038,6 +1041,46 @@ impl<'a, 'b> PeepholeSubstituteAlternateSyntax {
)
}

/// `new Int8Array(0)` -> `new Int8Array()` (also for other TypedArrays)
fn try_compress_typed_array_constructor(
&mut self,
e: &mut NewExpression<'a>,
ctx: Ctx<'a, 'b>,
) {
let Expression::Identifier(ident) = &e.callee else { return };
let name = ident.name.as_str();
if !Self::is_typed_array_name(name) || !ctx.is_global_reference(ident) {
return;
}

if e.arguments.len() == 1
&& e.arguments[0].as_expression().is_some_and(Expression::is_number_0)
{
e.arguments.clear();
self.changed = true;
}
}

/// Whether the name matches any TypedArray name.
///
/// See <https://tc39.es/ecma262/multipage/indexed-collections.html#sec-typedarray-objects> for the list of TypedArrays.
fn is_typed_array_name(name: &str) -> bool {
matches!(
name,
"Int8Array"
| "Uint8Array"
| "Uint8ClampedArray"
| "Int16Array"
| "Uint16Array"
| "Int32Array"
| "Uint32Array"
| "Float32Array"
| "Float64Array"
| "BigInt64Array"
| "BigUint64Array"
)
}

/// `typeof foo === 'number'` -> `typeof foo == 'number'`
fn try_compress_type_of_equal_string(&mut self, e: &mut BinaryExpression<'a>) {
let op = match e.operator {
Expand Down Expand Up @@ -1462,6 +1505,26 @@ mod test {
test_same("new RegExp(/foo/)");
}

#[test]
fn test_compress_typed_array_constructor() {
test("new Int8Array(0)", "new Int8Array()");
test("new Uint8Array(0)", "new Uint8Array()");
test("new Uint8ClampedArray(0)", "new Uint8ClampedArray()");
test("new Int16Array(0)", "new Int16Array()");
test("new Uint16Array(0)", "new Uint16Array()");
test("new Int32Array(0)", "new Int32Array()");
test("new Uint32Array(0)", "new Uint32Array()");
test("new Float32Array(0)", "new Float32Array()");
test("new Float64Array(0)", "new Float64Array()");
test("new BigInt64Array(0)", "new BigInt64Array()");
test("new BigUint64Array(0)", "new BigUint64Array()");

test_same("var Int8Array; new Int8Array(0)");
test_same("new Int8Array(1)");
test_same("new Int8Array(a)");
test_same("new Int8Array(0, a)");
}

#[test]
#[ignore]
fn test_split_comma_expressions() {
Expand Down
2 changes: 1 addition & 1 deletion tasks/minsize/minsize.snap
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Original | minified | minified | gzip | gzip | Fixture

544.10 kB | 71.76 kB | 72.48 kB | 26.15 kB | 26.20 kB | lodash.js

555.77 kB | 273.16 kB | 270.13 kB | 90.92 kB | 90.80 kB | d3.js
555.77 kB | 273.15 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

Expand Down

0 comments on commit d56020b

Please sign in to comment.