Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 21 additions & 23 deletions crates/oxc_minifier/src/peephole/substitute_alternate_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,12 @@ impl<'a> PeepholeOptimizations {

/// Compress `typeof foo == "undefined"`
///
/// - `typeof foo == "undefined"` (if foo is resolved) -> `foo === undefined`
/// - `typeof foo != "undefined"` (if foo is resolved) -> `foo !== undefined`
/// - `typeof foo == "undefined"` -> `typeof foo > "u"`
/// - `typeof foo != "undefined"` -> `typeof foo < "u"`
/// - `typeof foo == "undefined"` (if foo is not resolved) -> `typeof foo > "u"`
/// - `typeof foo != "undefined"` (if foo is not resolved) -> `typeof foo < "u"`
/// - `typeof foo == "undefined"` -> `foo === undefined`
/// - `typeof foo != "undefined"` -> `foo !== undefined`
/// - `typeof foo.bar == "undefined"` -> `foo.bar === undefined` (for any expression e.g.`typeof (foo + "")`)
/// - `typeof foo.bar != "undefined"` -> `foo.bar !== undefined` (for any expression e.g.`typeof (foo + "")`)
///
/// Enabled by `compress.typeofs`
fn try_compress_typeof_undefined(
Expand All @@ -183,24 +185,19 @@ impl<'a> PeepholeOptimizations {
_ => return None,
};
if let Expression::Identifier(ident) = &unary_expr.argument {
if !ctx.is_global_reference(ident) {
let Expression::UnaryExpression(unary_expr) =
ctx.ast.move_expression(&mut expr.left)
else {
unreachable!()
};
let right = ctx.ast.void_0(expr.right.span());
return Some(ctx.ast.expression_binary(
expr.span,
unary_expr.unbox().argument,
new_eq_op,
right,
));
if ctx.is_global_reference(ident) {
let left = ctx.ast.move_expression(&mut expr.left);
let right = ctx.ast.expression_string_literal(expr.right.span(), "u", None);
return Some(ctx.ast.expression_binary(expr.span, left, new_comp_op, right));
}
}

let Expression::UnaryExpression(unary_expr) = ctx.ast.move_expression(&mut expr.left)
else {
unreachable!()
};
let left = ctx.ast.move_expression(&mut expr.left);
let right = ctx.ast.expression_string_literal(expr.right.span(), "u", None);
Some(ctx.ast.expression_binary(expr.span, left, new_comp_op, right))
let right = ctx.ast.void_0(expr.right.span());
Some(ctx.ast.expression_binary(expr.span, unary_expr.unbox().argument, new_eq_op, right))
}

/// `a || (b || c);` -> `(a || b) || c;`
Expand Down Expand Up @@ -1498,6 +1495,10 @@ mod test {
test("typeof x !== 'undefined'; var x", "x !== void 0; var x");
// input and output both errors with same TDZ error
test("typeof x !== 'undefined'; let x", "x !== void 0; let x");

test("typeof x.y === 'undefined'", "x.y === void 0");
test("typeof x.y !== 'undefined'", "x.y !== void 0");
test("typeof (x + '') === 'undefined'", "x + '' === void 0");
}

/// Port from <https://github.com/evanw/esbuild/blob/v0.24.2/internal/js_parser/js_parser_test.go#L4658>
Expand All @@ -1512,9 +1513,6 @@ mod test {
test("typeof x == 'undefined'", "typeof x > 'u'");
test("'undefined' === typeof x", "typeof x > 'u'");
test("'undefined' == typeof x", "typeof x > 'u'");

test("typeof x.y === 'undefined'", "typeof x.y > 'u'");
test("typeof x.y !== 'undefined'", "typeof x.y < 'u'");
}

#[test]
Expand Down
4 changes: 2 additions & 2 deletions tasks/minsize/minsize.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Original | minified | minified | gzip | gzip | Fixture

173.90 kB | 59.68 kB | 59.82 kB | 19.25 kB | 19.33 kB | moment.js

287.63 kB | 89.54 kB | 90.07 kB | 31.07 kB | 31.95 kB | jquery.js
287.63 kB | 89.52 kB | 90.07 kB | 31.07 kB | 31.95 kB | jquery.js

342.15 kB | 117.69 kB | 118.14 kB | 43.66 kB | 44.37 kB | vue.js

Expand All @@ -21,7 +21,7 @@ Original | minified | minified | gzip | gzip | Fixture

3.20 MB | 1.01 MB | 1.01 MB | 325.18 kB | 331.56 kB | echarts.js

6.69 MB | 2.30 MB | 2.31 MB | 469.99 kB | 488.28 kB | antd.js
6.69 MB | 2.30 MB | 2.31 MB | 469.97 kB | 488.28 kB | antd.js

10.95 MB | 3.37 MB | 3.49 MB | 866.63 kB | 915.50 kB | typescript.js

Loading