Skip to content

Commit

Permalink
Merge branch 'better-reassignment-tracking'
Browse files Browse the repository at this point in the history
  • Loading branch information
lukastaegert committed May 15, 2018
2 parents 9445705 + 77d0503 commit 2879bb7
Show file tree
Hide file tree
Showing 102 changed files with 298 additions and 603 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -11,6 +11,7 @@
* Fix an issue with namespaces containing reexports ([#2157](https://github.com/rollup/rollup/pull/2157))
* Fix an issue with wrong paths of relative external imports ([#2160](https://github.com/rollup/rollup/pull/2160))
* Fix an issue when using default exports and `interop: false` ([#2149](https://github.com/rollup/rollup/pull/2149))
* Fix an issue when tree-shaking call expressions and reassigned variables ([#2186](https://github.com/rollup/rollup/pull/2186))
* Fix file paths in source maps ([#2161](https://github.com/rollup/rollup/pull/2161))
* Fix wrong file name in error message ([#2137](https://github.com/rollup/rollup/pull/2137))
* Always use npm 5 on CI ([#2185](https://github.com/rollup/rollup/pull/2185))
Expand Down
4 changes: 2 additions & 2 deletions bin/src/run/loadConfigFile.ts
Expand Up @@ -38,9 +38,9 @@ export default function loadConfigFile(
.then(({ code }: { code: string }) => {
// temporarily override require
const defaultLoader = require.extensions['.js'];
require.extensions['.js'] = (module, filename) => {
require.extensions['.js'] = (module: NodeModuleWithCompile, filename: string) => {
if (filename === configFile) {
(module as NodeModuleWithCompile)._compile(code, filename);
module._compile(code, filename);
} else {
defaultLoader(module, filename);
}
Expand Down
28 changes: 14 additions & 14 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -92,12 +92,12 @@
"rollup": "^0.58.2",
"rollup-plugin-buble": "^0.19.2",
"rollup-plugin-commonjs": "^9.1.3",
"rollup-plugin-json": "^2.3.0",
"rollup-plugin-json": "^3.0.0",
"rollup-plugin-node-resolve": "^3.3.0",
"rollup-plugin-replace": "^2.0.0",
"rollup-plugin-string": "^2.0.0",
"rollup-plugin-typescript": "^0.8.1",
"rollup-pluginutils": "^2.0.1",
"rollup-pluginutils": "^2.2.0",
"rollup-watch": "^4.3.1",
"sander": "^0.6.0",
"signal-exit": "^3.0.2",
Expand Down
2 changes: 1 addition & 1 deletion src/ast/Entity.ts
@@ -1,4 +1,4 @@
import ExecutionPathOptions from './ExecutionPathOptions';
import { ExecutionPathOptions } from './ExecutionPathOptions';
import { ObjectPath } from './values';

export interface Entity {
Expand Down
4 changes: 3 additions & 1 deletion src/ast/ExecutionPathOptions.ts
Expand Up @@ -26,7 +26,7 @@ export type RESULT_KEY = {};
export const RESULT_KEY: RESULT_KEY = {};
export type KeyTypes = OptionTypes | Entity | RESULT_KEY;

export default class ExecutionPathOptions {
export class ExecutionPathOptions {
private optionValues: Immutable.Map<KeyTypes, boolean | Entity | ExpressionEntity[]>;

static create() {
Expand Down Expand Up @@ -208,3 +208,5 @@ export default class ExecutionPathOptions {
return this.set(OptionTypes.IGNORE_RETURN_AWAIT_YIELD, value);
}
}

export const NEW_EXECUTION_PATH = ExecutionPathOptions.create();
4 changes: 2 additions & 2 deletions src/ast/nodes/ArrayExpression.ts
Expand Up @@ -3,7 +3,7 @@ import { SomeReturnExpressionCallback } from './shared/Expression';
import { ExpressionNode, NodeBase } from './shared/Node';
import * as NodeType from './NodeType';
import CallOptions from '../CallOptions';
import ExecutionPathOptions from '../ExecutionPathOptions';
import { ExecutionPathOptions } from '../ExecutionPathOptions';
import {
arrayMembers,
hasMemberEffectWhenCalled,
Expand All @@ -25,7 +25,7 @@ export default class ArrayExpression extends NodeBase {
options: ExecutionPathOptions
): boolean {
if (path.length === 1) {
return hasMemberEffectWhenCalled(arrayMembers, path[0], callOptions, options);
return hasMemberEffectWhenCalled(arrayMembers, path[0], this.included, callOptions, options);
}
return true;
}
Expand Down
7 changes: 4 additions & 3 deletions src/ast/nodes/ArrayPattern.ts
@@ -1,5 +1,5 @@
import { ObjectPath, UNKNOWN_EXPRESSION } from '../values';
import ExecutionPathOptions from '../ExecutionPathOptions';
import { EMPTY_PATH, ObjectPath, UNKNOWN_EXPRESSION } from '../values';
import { ExecutionPathOptions } from '../ExecutionPathOptions';
import { PatternNode } from './shared/Pattern';
import { ExpressionEntity } from './shared/Expression';
import { NodeBase } from './shared/Node';
Expand All @@ -20,7 +20,8 @@ export default class ArrayPattern extends NodeBase implements PatternNode {
hasEffectsWhenAssignedAtPath(path: ObjectPath, options: ExecutionPathOptions) {
if (path.length > 0) return true;
for (const element of this.elements) {
if (element !== null && element.hasEffectsWhenAssignedAtPath([], options)) return true;
if (element !== null && element.hasEffectsWhenAssignedAtPath(EMPTY_PATH, options))
return true;
}
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion src/ast/nodes/ArrowFunctionExpression.ts
Expand Up @@ -2,7 +2,7 @@ import Scope from '../scopes/Scope';
import ReturnValueScope from '../scopes/ReturnValueScope';
import BlockStatement, { isBlockStatement } from './BlockStatement';
import CallOptions from '../CallOptions';
import ExecutionPathOptions from '../ExecutionPathOptions';
import { ExecutionPathOptions } from '../ExecutionPathOptions';
import { ForEachReturnExpressionCallback, SomeReturnExpressionCallback } from './shared/Expression';
import { PatternNode } from './shared/Pattern';
import { ExpressionNode, GenericEsTreeNode, NodeBase } from './shared/Node';
Expand Down
10 changes: 6 additions & 4 deletions src/ast/nodes/AssignmentExpression.ts
@@ -1,8 +1,8 @@
import ExecutionPathOptions from '../ExecutionPathOptions';
import { ExecutionPathOptions, NEW_EXECUTION_PATH } from '../ExecutionPathOptions';
import { PatternNode } from './shared/Pattern';
import { ExpressionNode, NodeBase } from './shared/Node';
import * as NodeType from './NodeType';
import { ObjectPath } from '../values';
import { EMPTY_PATH, ObjectPath, UNKNOWN_PATH } from '../values';

export default class AssignmentExpression extends NodeBase {
type: NodeType.tAssignmentExpression;
Expand All @@ -11,14 +11,16 @@ export default class AssignmentExpression extends NodeBase {

bind() {
super.bind();
this.left.reassignPath([], ExecutionPathOptions.create());
this.left.reassignPath(EMPTY_PATH, NEW_EXECUTION_PATH);
// We can not propagate mutations of the new binding to the old binding with certainty
this.right.reassignPath(UNKNOWN_PATH, NEW_EXECUTION_PATH);
}

hasEffects(options: ExecutionPathOptions): boolean {
return (
this.right.hasEffects(options) ||
this.left.hasEffects(options) ||
this.left.hasEffectsWhenAssignedAtPath([], options)
this.left.hasEffectsWhenAssignedAtPath(EMPTY_PATH, options)
);
}

Expand Down
8 changes: 4 additions & 4 deletions src/ast/nodes/AssignmentPattern.ts
@@ -1,9 +1,9 @@
import ExecutionPathOptions from '../ExecutionPathOptions';
import { ExecutionPathOptions, NEW_EXECUTION_PATH } from '../ExecutionPathOptions';
import { PatternNode } from './shared/Pattern';
import { ExpressionEntity } from './shared/Expression';
import { ExpressionNode, NodeBase } from './shared/Node';
import * as NodeType from './NodeType';
import { ObjectPath } from '../values';
import { EMPTY_PATH, ObjectPath } from '../values';

export default class AssignmentPattern extends NodeBase implements PatternNode {
type: NodeType.tAssignmentPattern;
Expand All @@ -12,15 +12,15 @@ export default class AssignmentPattern extends NodeBase implements PatternNode {

bind() {
super.bind();
this.left.reassignPath([], ExecutionPathOptions.create());
this.left.reassignPath(EMPTY_PATH, NEW_EXECUTION_PATH);
}

declare(kind: string, init: ExpressionEntity | null) {
this.left.declare(kind, init);
}

hasEffectsWhenAssignedAtPath(path: ObjectPath, options: ExecutionPathOptions): boolean {
return path.length > 0 || this.left.hasEffectsWhenAssignedAtPath([], options);
return path.length > 0 || this.left.hasEffectsWhenAssignedAtPath(EMPTY_PATH, options);
}

reassignPath(path: ObjectPath, options: ExecutionPathOptions) {
Expand Down
2 changes: 1 addition & 1 deletion src/ast/nodes/AwaitExpression.ts
@@ -1,4 +1,4 @@
import ExecutionPathOptions from '../ExecutionPathOptions';
import { ExecutionPathOptions } from '../ExecutionPathOptions';
import * as NodeType from './NodeType';
import { ExpressionNode, NodeBase } from './shared/Node';

Expand Down
8 changes: 4 additions & 4 deletions src/ast/nodes/BinaryExpression.ts
@@ -1,5 +1,5 @@
import { ObjectPath, LiteralValueOrUnknown, UNKNOWN_VALUE } from '../values';
import ExecutionPathOptions from '../ExecutionPathOptions';
import { ObjectPath, LiteralValueOrUnknown, UNKNOWN_VALUE, EMPTY_PATH } from '../values';
import { ExecutionPathOptions } from '../ExecutionPathOptions';
import * as NodeType from './NodeType';
import { ExpressionNode, NodeBase } from './shared/Node';
import { LiteralValue } from './Literal';
Expand Down Expand Up @@ -39,10 +39,10 @@ export default class BinaryExpression extends NodeBase {

getLiteralValueAtPath(path: ObjectPath): LiteralValueOrUnknown {
if (path.length > 0) return UNKNOWN_VALUE;
const leftValue = this.left.getLiteralValueAtPath([]);
const leftValue = this.left.getLiteralValueAtPath(EMPTY_PATH);
if (leftValue === UNKNOWN_VALUE) return UNKNOWN_VALUE;

const rightValue = this.right.getLiteralValueAtPath([]);
const rightValue = this.right.getLiteralValueAtPath(EMPTY_PATH);
if (rightValue === UNKNOWN_VALUE) return UNKNOWN_VALUE;

const operatorFn = binaryOperators[this.operator];
Expand Down
2 changes: 1 addition & 1 deletion src/ast/nodes/BlockStatement.ts
@@ -1,6 +1,6 @@
import BlockScope from '../scopes/BlockScope';
import { UNKNOWN_EXPRESSION } from '../values';
import ExecutionPathOptions from '../ExecutionPathOptions';
import { ExecutionPathOptions } from '../ExecutionPathOptions';
import Scope from '../scopes/Scope';
import MagicString from 'magic-string';
import { Node, StatementBase, StatementNode } from './shared/Node';
Expand Down
2 changes: 1 addition & 1 deletion src/ast/nodes/BreakStatement.ts
@@ -1,4 +1,4 @@
import ExecutionPathOptions from '../ExecutionPathOptions';
import { ExecutionPathOptions } from '../ExecutionPathOptions';
import Identifier from './Identifier';
import * as NodeType from './NodeType';
import { StatementBase } from './shared/Node';
Expand Down
12 changes: 8 additions & 4 deletions src/ast/nodes/CallExpression.ts
@@ -1,11 +1,11 @@
import CallOptions from '../CallOptions';
import ExecutionPathOptions from '../ExecutionPathOptions';
import { ExecutionPathOptions, NEW_EXECUTION_PATH } from '../ExecutionPathOptions';
import SpreadElement from './SpreadElement';
import { isIdentifier } from './Identifier';
import Identifier from './Identifier';
import { ForEachReturnExpressionCallback, SomeReturnExpressionCallback } from './shared/Expression';
import * as NodeType from './NodeType';
import { ExpressionNode, NodeBase } from './shared/Node';
import { ObjectPath } from '../values';
import { ObjectPath, UNKNOWN_PATH } from '../values';

export default class CallExpression extends NodeBase {
type: NodeType.tCallExpression;
Expand All @@ -16,7 +16,7 @@ export default class CallExpression extends NodeBase {

bind() {
super.bind();
if (isIdentifier(this.callee)) {
if (this.callee instanceof Identifier) {
const variable = this.scope.findVariable(this.callee.name);

if (variable.isNamespace) {
Expand All @@ -40,6 +40,10 @@ export default class CallExpression extends NodeBase {
);
}
}
for (const argument of this.arguments) {
// This will make sure all properties of parameters behave as "unknown"
argument.reassignPath(UNKNOWN_PATH, NEW_EXECUTION_PATH);
}
}

forEachReturnExpressionWhenCalledAtPath(
Expand Down
6 changes: 3 additions & 3 deletions src/ast/nodes/ClassBody.ts
@@ -1,9 +1,9 @@
import { NodeBase } from './shared/Node';
import ExecutionPathOptions from '../ExecutionPathOptions';
import { ExecutionPathOptions } from '../ExecutionPathOptions';
import CallOptions from '../CallOptions';
import MethodDefinition from './MethodDefinition';
import * as NodeType from './NodeType';
import { ObjectPath } from '../values';
import { EMPTY_PATH, ObjectPath } from '../values';

export default class ClassBody extends NodeBase {
type: NodeType.tClassBody;
Expand All @@ -21,7 +21,7 @@ export default class ClassBody extends NodeBase {
}
return (
this.classConstructor !== null &&
this.classConstructor.hasEffectsWhenCalledAtPath([], callOptions, options)
this.classConstructor.hasEffectsWhenCalledAtPath(EMPTY_PATH, callOptions, options)
);
}

Expand Down
6 changes: 3 additions & 3 deletions src/ast/nodes/ConditionalExpression.ts
@@ -1,5 +1,5 @@
import { ObjectPath, LiteralValueOrUnknown, UNKNOWN_VALUE } from '../values';
import ExecutionPathOptions from '../ExecutionPathOptions';
import { ObjectPath, LiteralValueOrUnknown, UNKNOWN_VALUE, EMPTY_PATH } from '../values';
import { ExecutionPathOptions } from '../ExecutionPathOptions';
import CallOptions from '../CallOptions';
import MagicString from 'magic-string';
import { ForEachReturnExpressionCallback, SomeReturnExpressionCallback } from './shared/Expression';
Expand Down Expand Up @@ -185,7 +185,7 @@ export default class ConditionalExpression extends NodeBase {

private getTestValue() {
if (this.hasUnknownTestValue) return UNKNOWN_VALUE;
const value = this.test.getLiteralValueAtPath([]);
const value = this.test.getLiteralValueAtPath(EMPTY_PATH);
if (value === UNKNOWN_VALUE) {
this.hasUnknownTestValue = true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/ast/nodes/DoWhileStatement.ts
@@ -1,4 +1,4 @@
import ExecutionPathOptions from '../ExecutionPathOptions';
import { ExecutionPathOptions } from '../ExecutionPathOptions';
import { ExpressionNode, StatementNode, StatementBase } from './shared/Node';
import * as NodeType from './NodeType';

Expand Down
2 changes: 1 addition & 1 deletion src/ast/nodes/ExportNamedDeclaration.ts
@@ -1,5 +1,5 @@
import { Node, NodeBase } from './shared/Node';
import ExecutionPathOptions from '../ExecutionPathOptions';
import { ExecutionPathOptions } from '../ExecutionPathOptions';
import Literal from './Literal';
import MagicString from 'magic-string';
import ExportSpecifier from './ExportSpecifier';
Expand Down
6 changes: 4 additions & 2 deletions src/ast/nodes/ForInStatement.ts
@@ -1,12 +1,13 @@
import BlockScope from '../scopes/BlockScope';
import VariableDeclaration from './VariableDeclaration';
import Scope from '../scopes/Scope';
import ExecutionPathOptions from '../ExecutionPathOptions';
import { ExecutionPathOptions } from '../ExecutionPathOptions';
import { PatternNode } from './shared/Pattern';
import * as NodeType from './NodeType';
import { ExpressionNode, Node, StatementBase, StatementNode } from './shared/Node';
import MagicString from 'magic-string';
import { NO_SEMICOLON, RenderOptions } from '../../utils/renderHelpers';
import { EMPTY_PATH } from '../values';

export function isForInStatement(node: Node): node is ForInStatement {
return node.type === NodeType.ForInStatement;
Expand All @@ -25,7 +26,8 @@ export default class ForInStatement extends StatementBase {
hasEffects(options: ExecutionPathOptions): boolean {
return (
(this.left &&
(this.left.hasEffects(options) || this.left.hasEffectsWhenAssignedAtPath([], options))) ||
(this.left.hasEffects(options) ||
this.left.hasEffectsWhenAssignedAtPath(EMPTY_PATH, options))) ||
(this.right && this.right.hasEffects(options)) ||
this.body.hasEffects(options.setIgnoreBreakStatements())
);
Expand Down

0 comments on commit 2879bb7

Please sign in to comment.