From 0ce529584225c87ff7e93c85c8eca3ffaff78224 Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Tue, 5 Jan 2021 08:39:48 +0100 Subject: [PATCH] Treeshake chained assignment expressions --- src/ast/nodes/AssignmentExpression.ts | 20 ++++++++++++++++--- .../samples/chained-assignments/_config.js | 3 +++ .../samples/chained-assignments/_expected.js | 8 ++++++++ test/form/samples/chained-assignments/main.js | 8 ++++++++ .../samples/nested-member-access/_expected.js | 4 +--- .../form/samples/nested-member-access/main.js | 4 ++-- 6 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 test/form/samples/chained-assignments/_config.js create mode 100644 test/form/samples/chained-assignments/_expected.js create mode 100644 test/form/samples/chained-assignments/main.js diff --git a/src/ast/nodes/AssignmentExpression.ts b/src/ast/nodes/AssignmentExpression.ts index 1bf17272651..44bbc3de7d2 100644 --- a/src/ast/nodes/AssignmentExpression.ts +++ b/src/ast/nodes/AssignmentExpression.ts @@ -5,7 +5,7 @@ import { RenderOptions } from '../../utils/renderHelpers'; import { getSystemExportFunctionLeft } from '../../utils/systemJsRendering'; -import { HasEffectsContext, InclusionContext } from '../ExecutionContext'; +import { createHasEffectsContext, HasEffectsContext, InclusionContext } from '../ExecutionContext'; import { EMPTY_PATH, ObjectPath, UNKNOWN_PATH } from '../utils/PathTracker'; import Variable from '../variables/Variable'; import * as NodeType from './NodeType'; @@ -48,13 +48,27 @@ export default class AssignmentExpression extends NodeBase { include(context: InclusionContext, includeChildrenRecursively: IncludeChildren): void { if (!this.deoptimized) this.applyDeoptimizations(); this.included = true; - this.left.include(context, includeChildrenRecursively); + let hasEffectsContext; + if ( + includeChildrenRecursively || + this.operator !== '=' || + this.left.included || + ((hasEffectsContext = createHasEffectsContext()), + this.left.hasEffects(hasEffectsContext) || + this.left.hasEffectsWhenAssignedAtPath(EMPTY_PATH, hasEffectsContext)) + ) { + this.left.include(context, includeChildrenRecursively); + } this.right.include(context, includeChildrenRecursively); } render(code: MagicString, options: RenderOptions) { - this.left.render(code, options); this.right.render(code, options); + if (this.left.included) { + this.left.render(code, options); + } else { + code.remove(this.start, this.right.start); + } if (options.format === 'system') { const exportNames = this.left.variable && options.exportNamesByVariable.get(this.left.variable); diff --git a/test/form/samples/chained-assignments/_config.js b/test/form/samples/chained-assignments/_config.js new file mode 100644 index 00000000000..ddbf4e78e64 --- /dev/null +++ b/test/form/samples/chained-assignments/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'treeshakes chained assignments' +}; diff --git a/test/form/samples/chained-assignments/_expected.js b/test/form/samples/chained-assignments/_expected.js new file mode 100644 index 00000000000..e27cbb566aa --- /dev/null +++ b/test/form/samples/chained-assignments/_expected.js @@ -0,0 +1,8 @@ +let a, d; +a = 1; +d = 2; +console.log(a, d); + +let e = 'first', f = 'second'; +e += f += 'third'; +console.log(e); diff --git a/test/form/samples/chained-assignments/main.js b/test/form/samples/chained-assignments/main.js new file mode 100644 index 00000000000..9ed53d07748 --- /dev/null +++ b/test/form/samples/chained-assignments/main.js @@ -0,0 +1,8 @@ +let a, b, c, d; +a = b = 1; +c = d = 2; +console.log(a, d); + +let e = 'first', f = 'second'; +e += f += 'third'; +console.log(e); diff --git a/test/form/samples/nested-member-access/_expected.js b/test/form/samples/nested-member-access/_expected.js index efa8afcd2c8..cf136c54870 100644 --- a/test/form/samples/nested-member-access/_expected.js +++ b/test/form/samples/nested-member-access/_expected.js @@ -6,9 +6,7 @@ const retainedResult2 = retained2.foo.bar; const retained3 = void {}; const retainedResult3 = retained3.foo; - -let retained4a; -const retained4b = retained4a = undefined; +const retained4b = undefined; const retainedResult4 = retained4b.foo; const retained5 = 1 + 2; diff --git a/test/form/samples/nested-member-access/main.js b/test/form/samples/nested-member-access/main.js index 8b42d3c5ad3..323ca9e7885 100644 --- a/test/form/samples/nested-member-access/main.js +++ b/test/form/samples/nested-member-access/main.js @@ -32,8 +32,8 @@ const retainedResult2 = retained2.foo.bar; const retained3 = void {}; const retainedResult3 = retained3.foo; -let retained4a; -const retained4b = retained4a = undefined; +let removed4a; +const retained4b = removed4a = undefined; const retainedResult4 = retained4b.foo; const retained5 = 1 + 2;