Skip to content

Commit

Permalink
feat(minifier): constant fold instanceof
Browse files Browse the repository at this point in the history
  • Loading branch information
sapphi-red committed Dec 27, 2024
1 parent 75264ed commit 5519dd0
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 1 deletion.
21 changes: 21 additions & 0 deletions crates/oxc_ecmascript/src/constant_evaluation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,27 @@ pub trait ConstantEvaluation<'a> {
}
None
}
BinaryOperator::Instanceof => {
if left.may_have_side_effects() {
return None;
}

let left_ty = ValueType::from(left);
if left_ty == ValueType::Undetermined {
return None;
}
if left_ty == ValueType::Object {
if let Some(right_ident) = right.get_identifier_reference() {
if right_ident.name == "Object" && self.is_global_reference(right_ident) {
return Some(ConstantValue::Boolean(true));
}
}
None
} else {
// Non-object types are never instances.
Some(ConstantValue::Boolean(false))
}
}
_ => None,
}
}
Expand Down
42 changes: 41 additions & 1 deletion crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,8 @@ impl<'a, 'b> PeepholeFoldConstants {
| BinaryOperator::Division
| BinaryOperator::Remainder
| BinaryOperator::Multiplication
| BinaryOperator::Exponential => {
| BinaryOperator::Exponential
| BinaryOperator::Instanceof => {
ctx.eval_binary_expression(e).map(|v| ctx.value_to_expr(e.span, v))
}
BinaryOperator::Addition => Self::try_fold_add(e, ctx),
Expand Down Expand Up @@ -1503,6 +1504,45 @@ mod test {
test("(+x & 1) & 2", "+x & 0");
}

#[test]
fn test_fold_instance_of() {
// Non object types are never instances of anything.
test("64 instanceof Object", "false");
test("64 instanceof Number", "false");
test("'' instanceof Object", "false");
test("'' instanceof String", "false");
test("true instanceof Object", "false");
test("true instanceof Boolean", "false");
test("!0 instanceof Object", "false");
test("!0 instanceof Boolean", "false");
test("false instanceof Object", "false");
test("null instanceof Object", "false");
test("undefined instanceof Object", "false");
test("NaN instanceof Object", "false");
test("Infinity instanceof Object", "false");

// Array and object literals are known to be objects.
test("[] instanceof Object", "true");
test("({}) instanceof Object", "true");

// These cases is foldable, but no handled currently.
test_same("new Foo() instanceof Object");
// These would require type information to fold.
test_same("[] instanceof Foo");
test_same("({}) instanceof Foo");

test("(function() {}) instanceof Object", "true");

// An unknown value should never be folded.
test_same("x instanceof Foo");
}

#[test]
fn test_fold_instance_of_additional() {
test("(typeof {}) instanceof Object", "false");
test("(+{}) instanceof Number", "false");
}

#[test]
fn test_fold_left_child_op() {
test_same("x & infinity & 2"); // FIXME: want x & 0
Expand Down

0 comments on commit 5519dd0

Please sign in to comment.