mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
feat(minifier): compress typeof a.b === 'undefined' to a.b === void 0 (#8751)
The special behavior of `typeof` is only for the identifier, so it should be safe to compress `typeof a.b === 'undefined'` (and other expressions) to `a.b === void 0`.
This commit is contained in:
parent
f7f2d2f93a
commit
ad14403f9e
2 changed files with 23 additions and 25 deletions
|
|
@ -156,10 +156,12 @@ impl<'a> PeepholeOptimizations {
|
||||||
|
|
||||||
/// Compress `typeof foo == "undefined"`
|
/// Compress `typeof foo == "undefined"`
|
||||||
///
|
///
|
||||||
/// - `typeof foo == "undefined"` (if foo is resolved) -> `foo === undefined`
|
/// - `typeof foo == "undefined"` (if foo is not resolved) -> `typeof foo > "u"`
|
||||||
/// - `typeof foo != "undefined"` (if foo is resolved) -> `foo !== undefined`
|
/// - `typeof foo != "undefined"` (if foo is not resolved) -> `typeof foo < "u"`
|
||||||
/// - `typeof foo == "undefined"` -> `typeof foo > "u"`
|
/// - `typeof foo == "undefined"` -> `foo === undefined`
|
||||||
/// - `typeof foo != "undefined"` -> `typeof foo < "u"`
|
/// - `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`
|
/// Enabled by `compress.typeofs`
|
||||||
fn try_compress_typeof_undefined(
|
fn try_compress_typeof_undefined(
|
||||||
|
|
@ -183,24 +185,19 @@ impl<'a> PeepholeOptimizations {
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
if let Expression::Identifier(ident) = &unary_expr.argument {
|
if let Expression::Identifier(ident) = &unary_expr.argument {
|
||||||
if !ctx.is_global_reference(ident) {
|
if ctx.is_global_reference(ident) {
|
||||||
let Expression::UnaryExpression(unary_expr) =
|
let left = ctx.ast.move_expression(&mut expr.left);
|
||||||
ctx.ast.move_expression(&mut expr.left)
|
let right = ctx.ast.expression_string_literal(expr.right.span(), "u", None);
|
||||||
else {
|
return Some(ctx.ast.expression_binary(expr.span, left, new_comp_op, right));
|
||||||
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,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.void_0(expr.right.span());
|
||||||
let right = ctx.ast.expression_string_literal(expr.right.span(), "u", None);
|
Some(ctx.ast.expression_binary(expr.span, unary_expr.unbox().argument, new_eq_op, right))
|
||||||
Some(ctx.ast.expression_binary(expr.span, left, new_comp_op, right))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `a || (b || c);` -> `(a || b) || c;`
|
/// `a || (b || c);` -> `(a || b) || c;`
|
||||||
|
|
@ -1498,6 +1495,10 @@ mod test {
|
||||||
test("typeof x !== 'undefined'; var x", "x !== void 0; var x");
|
test("typeof x !== 'undefined'; var x", "x !== void 0; var x");
|
||||||
// input and output both errors with same TDZ error
|
// input and output both errors with same TDZ error
|
||||||
test("typeof x !== 'undefined'; let x", "x !== void 0; let x");
|
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>
|
/// Port from <https://github.com/evanw/esbuild/blob/v0.24.2/internal/js_parser/js_parser_test.go#L4658>
|
||||||
|
|
@ -1512,9 +1513,6 @@ mod test {
|
||||||
test("typeof x == 'undefined'", "typeof x > 'u'");
|
test("typeof x == 'undefined'", "typeof x > 'u'");
|
||||||
test("'undefined' === typeof x", "typeof x > 'u'");
|
test("'undefined' === typeof x", "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]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -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
|
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
|
342.15 kB | 117.69 kB | 118.14 kB | 43.66 kB | 44.37 kB | vue.js
|
||||||
|
|
||||||
|
|
@ -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
|
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
|
10.95 MB | 3.37 MB | 3.49 MB | 866.63 kB | 915.50 kB | typescript.js
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue