Skip to content

Commit

Permalink
Add regression tests for instanceof (rollup#4525)
Browse files Browse the repository at this point in the history
* Treeshake instanceof

* Fix side effect and self-reference handling

* Remove feature and add regression test
  • Loading branch information
lukastaegert authored and pos777 committed Jun 18, 2022
1 parent 0fa9422 commit 7959315
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 9 deletions.
39 changes: 31 additions & 8 deletions src/ast/nodes/BinaryExpression.ts
Expand Up @@ -16,8 +16,32 @@ import type * as NodeType from './NodeType';
import { type LiteralValueOrUnknown, UnknownValue } from './shared/Expression';
import { type ExpressionNode, NodeBase } from './shared/Node';

type Operator =
| '!='
| '!=='
| '%'
| '&'
| '*'
| '**'
| '+'
| '-'
| '/'
| '<'
| '<<'
| '<='
| '=='
| '==='
| '>'
| '>='
| '>>'
| '>>>'
| '^'
| '|'
| 'in'
| 'instanceof';

const binaryOperators: {
[operator: string]: (left: LiteralValue, right: LiteralValue) => LiteralValueOrUnknown;
[operator in Operator]?: (left: LiteralValue, right: LiteralValue) => LiteralValueOrUnknown;
} = {
'!=': (left, right) => left != right,
'!==': (left, right) => left !== right,
Expand All @@ -29,15 +53,13 @@ const binaryOperators: {
'+': (left: any, right: any) => left + right,
'-': (left: any, right: any) => left - right,
'/': (left: any, right: any) => left / right,
'<': (left, right) => (left as NonNullable<LiteralValue>) < (right as NonNullable<LiteralValue>),
'<': (left, right) => left! < right!,
'<<': (left: any, right: any) => left << right,
'<=': (left, right) =>
(left as NonNullable<LiteralValue>) <= (right as NonNullable<LiteralValue>),
'<=': (left, right) => left! <= right!,
'==': (left, right) => left == right,
'===': (left, right) => left === right,
'>': (left, right) => (left as NonNullable<LiteralValue>) > (right as NonNullable<LiteralValue>),
'>=': (left, right) =>
(left as NonNullable<LiteralValue>) >= (right as NonNullable<LiteralValue>),
'>': (left, right) => left! > right!,
'>=': (left, right) => left! >= right!,
'>>': (left: any, right: any) => left >> right,
'>>>': (left: any, right: any) => left >>> right,
'^': (left: any, right: any) => left ^ right,
Expand Down Expand Up @@ -79,8 +101,9 @@ export default class BinaryExpression extends NodeBase implements DeoptimizableE
this.operator === '+' &&
this.parent instanceof ExpressionStatement &&
this.left.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this) === ''
)
) {
return true;
}
return super.hasEffects(context);
}

Expand Down
3 changes: 2 additions & 1 deletion src/ast/nodes/NewExpression.ts
Expand Up @@ -28,8 +28,9 @@ export default class NewExpression extends NodeBase {
if (
(this.context.options.treeshake as NormalizedTreeshakingOptions).annotations &&
this.annotations
)
) {
return false;
}
return (
this.callee.hasEffects(context) ||
this.callee.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context)
Expand Down
3 changes: 3 additions & 0 deletions test/function/samples/instanceof/left-hand-effect/_config.js
@@ -0,0 +1,3 @@
module.exports = {
description: 'retains side effects in the left hand side of instanceof'
};
14 changes: 14 additions & 0 deletions test/function/samples/instanceof/left-hand-effect/main.js
@@ -0,0 +1,14 @@
let effect = false;

class Bar {}
class Foo {
constructor() {
effect = true;
}
}

if (new Foo() instanceof Bar) {
assert.fail('Wrong instance relation');
}

assert.ok(effect);
3 changes: 3 additions & 0 deletions test/function/samples/instanceof/right-hand-effect/_config.js
@@ -0,0 +1,3 @@
module.exports = {
description: 'retains side effects in the right hand side of instanceof'
};
14 changes: 14 additions & 0 deletions test/function/samples/instanceof/right-hand-effect/main.js
@@ -0,0 +1,14 @@
let effect = false;

class Foo {}

if (
new Foo() instanceof
class {
[(effect = true)]() {}
}
) {
assert.fail('Wrong instance relation');
}

assert.ok(effect);
3 changes: 3 additions & 0 deletions test/function/samples/instanceof/used-parameter/_config.js
@@ -0,0 +1,3 @@
module.exports = {
description: 'retains instanceof for function parameters'
};
12 changes: 12 additions & 0 deletions test/function/samples/instanceof/used-parameter/main.js
@@ -0,0 +1,12 @@
let effect = false;

class Foo {}

function checkInstance(instance) {
if (instance instanceof Foo) {
effect = true;
}
}

checkInstance(new Foo());
assert.ok(effect);
3 changes: 3 additions & 0 deletions test/function/samples/instanceof/used/_config.js
@@ -0,0 +1,3 @@
module.exports = {
description: 'retains instanceof if it is true'
};
5 changes: 5 additions & 0 deletions test/function/samples/instanceof/used/main.js
@@ -0,0 +1,5 @@
class Foo {}

if (!(new Foo() instanceof Foo)) {
assert.fail('instanceof not resolved correctly');
}

0 comments on commit 7959315

Please sign in to comment.