fix(minifier): reference read has side effect (#6851)

This commit is contained in:
Boshen 2024-10-24 08:32:38 +00:00
parent c658d9336d
commit 686727fc96
4 changed files with 21 additions and 66 deletions

View file

@ -430,22 +430,6 @@ pub trait ConstantEvaluation<'a> {
left_string.cmp(&right_string) == Ordering::Less,
));
}
// Special case: `typeof a < typeof a` is always false.
if let (Expression::UnaryExpression(left), Expression::UnaryExpression(right)) =
(left_expr, right_expr)
{
if (left.operator, right.operator) == (UnaryOperator::Typeof, UnaryOperator::Typeof)
{
if let (Expression::Identifier(left), Expression::Identifier(right)) =
(&left.argument, &right.argument)
{
if left.name == right.name {
return Some(ConstantValue::Boolean(false));
}
}
}
}
}
// TODO: bigint is handled very differently in the spec

View file

@ -33,11 +33,11 @@ impl<'a, 'b> CheckForStateChange<'a, 'b> for Expression<'a> {
.expressions
.iter()
.any(|expr| expr.check_for_state_change(check_for_new_objects)),
Self::Identifier(_ident) =>
/* TODO: ident.reference_flags == ReferenceFlags::Write */
{
false
}
Self::Identifier(ident) => match ident.name.as_str() {
"undefined" | "NaN" | "Infinity" => false,
// Reference read can have a side effect.
_ => true,
},
Self::UnaryExpression(unary_expr) => {
unary_expr.check_for_state_change(check_for_new_objects)
}

View file

@ -6,7 +6,7 @@ use oxc_ecmascript::{
use oxc_span::{GetSpan, SPAN};
use oxc_syntax::{
number::{NumberBase, ToJsString},
operator::{BinaryOperator, LogicalOperator, UnaryOperator},
operator::{BinaryOperator, LogicalOperator},
};
use oxc_traverse::{Ancestor, Traverse, TraverseCtx};
@ -411,23 +411,6 @@ impl<'a, 'b> PeepholeFoldConstants {
return Tri::from(left_string == right_string);
}
if let (Expression::UnaryExpression(left), Expression::UnaryExpression(right)) =
(left_expr, right_expr)
{
if (left.operator, right.operator)
== (UnaryOperator::Typeof, UnaryOperator::Typeof)
{
if let (Expression::Identifier(left), Expression::Identifier(right)) =
(&left.argument, &right.argument)
{
if left.name == right.name {
// Special case, typeof a == typeof a is always true.
return Tri::True;
}
}
}
}
Tri::Unknown
}
ValueType::Undefined | ValueType::Null => Tri::True,
@ -713,28 +696,28 @@ mod test {
fn test_boolean_number_comparison() {
test_same("!x==+y");
test_same("!x<=+y");
test("!x !== +y", "true");
test_same("!x !== +y");
}
#[test]
fn test_number_boolean_comparison() {
test_same("+x==!y");
test_same("+x<=!y");
test("+x === !y", "false");
test_same("+x === !y");
}
#[test]
fn test_boolean_string_comparison() {
test_same("!x==''+y");
test_same("!x<=''+y");
test("!x !== '' + y", "true");
test_same("!x !== '' + y");
}
#[test]
fn test_string_boolean_comparison() {
test_same("''+x==!y");
test_same("''+x<=!y");
test("'' + x === !y", "false");
test_same("'' + x === !y");
}
#[test]
@ -746,8 +729,8 @@ mod test {
test("+'a' < +'b'", "false");
test_same("typeof a < 'a'");
test_same("'a' >= typeof a");
test("typeof a < typeof a", "false");
test("typeof a >= typeof a", "true");
test_same("typeof a < typeof a");
test_same("typeof a >= typeof a");
test("typeof 3 > typeof 4", "false");
test("typeof function() {} < typeof function() {}", "false");
test("'a' == 'a'", "true");
@ -756,11 +739,11 @@ mod test {
test_same("typeof a != 'number'");
test_same("'undefined' == typeof a");
test_same("'undefined' == typeof a");
test("typeof a == typeof a", "true");
test_same("typeof a == typeof a");
test("'a' === 'a'", "true");
test("'b' !== 'a'", "true");
test("typeof a === typeof a", "true");
test("typeof a !== typeof a", "false");
test_same("typeof a === typeof a");
test_same("typeof a !== typeof a");
test_same("'' + x <= '' + y");
test_same("'' + x != '' + y");
test_same("'' + x === '' + y");
@ -783,7 +766,7 @@ mod test {
test("1 !== '1'", "true");
test_same("+x>''+y");
test_same("+x==''+y");
test("+x !== '' + y", "true");
test_same("+x !== '' + y");
}
#[test]
@ -799,7 +782,7 @@ mod test {
test("'1' !== 1", "true");
test_same("''+x<+y");
test_same("''+x==+y");
test("'' + x === +y", "false");
test_same("'' + x === +y");
}
#[test]
@ -901,8 +884,8 @@ mod test {
test_same("x>=NaN");
test_same("NaN==x");
test_same("x!=NaN");
test("NaN === x", "false");
test("x !== NaN", "true");
test_same("NaN === x");
test_same("x !== NaN");
test_same("NaN==foo()");
}
@ -1109,7 +1092,7 @@ mod test {
fn test_fold_void() {
test_same("void 0");
test("void 1", "void 0");
test("void x", "void 0");
test_same("void x");
test_same("void x()");
}

View file

@ -2,7 +2,7 @@ commit: 06454619
runtime Summary:
AST Parsed : 18444/18444 (100.00%)
Positive Passed: 18269/18444 (99.05%)
Positive Passed: 18273/18444 (99.07%)
tasks/coverage/test262/test/annexB/language/function-code/if-decl-else-decl-a-func-existing-block-fn-no-init.js
minify error: Test262Error: Expected SameValue(«function f(){}», «undefined») to be true
@ -420,15 +420,6 @@ minify error: Test262Error: #3.2: -0 - 0 === - 0. Actual: +0
tasks/coverage/test262/test/language/expressions/super/call-spread-obj-getter-init.js
transform error: Test262Error: Expected SameValue(«true», «false») to be true
tasks/coverage/test262/test/language/expressions/template-literal/literal-expr-tostr-error.js
minify error: Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all
tasks/coverage/test262/test/language/expressions/template-literal/middle-list-many-expr-tostr-error.js
minify error: Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all
tasks/coverage/test262/test/language/expressions/template-literal/middle-list-one-expr-tostr-error.js
minify error: Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all
tasks/coverage/test262/test/language/expressions/unary-plus/S11.4.6_A3_T3.js
minify error: Test262Error: #4: +"INFINITY" === Not-a-Number. Actual: Infinity
@ -438,9 +429,6 @@ minify error: Test262Error: #3.2: +(-0) === -0. Actual: +0
tasks/coverage/test262/test/language/expressions/unary-plus/bigint-throws.js
minify error: Test262Error: +0n throws TypeError Expected a TypeError to be thrown but no exception was thrown at all
tasks/coverage/test262/test/language/expressions/void/S11.4.2_A2_T2.js
minify error: Test262Error: Expected a ReferenceError to be thrown but no exception was thrown at all
tasks/coverage/test262/test/language/global-code/decl-func.js
codegen error: Test262Error: descriptor should not be configurable