From 15680c2caf41917746a5152baf3195fad45ce32e Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Sun, 5 May 2019 21:19:51 -0700 Subject: [PATCH 1/2] Shake exports with pure property assignments --- .../scope-hoisting/es6/pure-assignment/a.js | 3 ++ .../scope-hoisting/es6/pure-assignment/b.js | 4 +++ .../integration-tests/test/scope-hoisting.js | 19 +++++++++++ .../src/scope-hoisting/shake.js | 33 ++++++++++--------- 4 files changed, 43 insertions(+), 16 deletions(-) create mode 100644 packages/core/integration-tests/test/integration/scope-hoisting/es6/pure-assignment/a.js create mode 100644 packages/core/integration-tests/test/integration/scope-hoisting/es6/pure-assignment/b.js diff --git a/packages/core/integration-tests/test/integration/scope-hoisting/es6/pure-assignment/a.js b/packages/core/integration-tests/test/integration/scope-hoisting/es6/pure-assignment/a.js new file mode 100644 index 00000000000..1ce7667c325 --- /dev/null +++ b/packages/core/integration-tests/test/integration/scope-hoisting/es6/pure-assignment/a.js @@ -0,0 +1,3 @@ +import {foo} from './b'; + +output = foo; diff --git a/packages/core/integration-tests/test/integration/scope-hoisting/es6/pure-assignment/b.js b/packages/core/integration-tests/test/integration/scope-hoisting/es6/pure-assignment/b.js new file mode 100644 index 00000000000..919f23d1fca --- /dev/null +++ b/packages/core/integration-tests/test/integration/scope-hoisting/es6/pure-assignment/b.js @@ -0,0 +1,4 @@ +export const foo = 2; + +export function bar() {} +bar.displayName = 'hello'; diff --git a/packages/core/integration-tests/test/scope-hoisting.js b/packages/core/integration-tests/test/scope-hoisting.js index df12a4a00ec..1b69a93d211 100644 --- a/packages/core/integration-tests/test/scope-hoisting.js +++ b/packages/core/integration-tests/test/scope-hoisting.js @@ -549,6 +549,25 @@ describe('scope hoisting', function() { let output = await run(b); assert.deepEqual(output, 'bar'); }); + + it('should shake pure property assignments', async function() { + let b = await bundle( + path.join( + __dirname, + '/integration/scope-hoisting/es6/pure-assignment/a.js' + ) + ); + + let output = await run(b); + assert.deepEqual(output, 2); + + let contents = await fs.readFile( + path.join(__dirname, 'dist/a.js'), + 'utf8' + ); + assert(!/bar/.test(contents)); + assert(!/displayName/.test(contents)); + }); }); describe('commonjs', function() { diff --git a/packages/core/parcel-bundler/src/scope-hoisting/shake.js b/packages/core/parcel-bundler/src/scope-hoisting/shake.js index d8f37b09e8a..6a22b18ebe6 100644 --- a/packages/core/parcel-bundler/src/scope-hoisting/shake.js +++ b/packages/core/parcel-bundler/src/scope-hoisting/shake.js @@ -1,7 +1,5 @@ const t = require('@babel/types'); -const EXPORTS_RE = /^\$([^$]+)\$exports$/; - /** * This is a small small implementation of dead code removal specialized to handle * removing unused exports. All other dead code removal happens in workers on each @@ -44,31 +42,24 @@ function getUnusedBinding(path, name) { return null; } - if (isPure(binding)) { + let pure = isPure(binding); + if (!binding.referenced && pure) { return binding; } - if (!EXPORTS_RE.test(name)) { - return null; - } - // Is there any references which aren't simple assignments? let bailout = binding.referencePaths.some( path => !isExportAssignment(path) && !isUnusedWildcard(path) ); - if (bailout) { - return null; - } else { + if (!bailout && pure) { return binding; } + + return null; } function isPure(binding) { - if (binding.referenced) { - return false; - } - if ( binding.path.isVariableDeclarator() && binding.path.get('id').isIdentifier() @@ -85,7 +76,8 @@ function isExportAssignment(path) { // match "path.any = any;" path.parentPath.isMemberExpression() && path.parentPath.parentPath.isAssignmentExpression() && - path.parentPath.parentPath.node.left === path.parentPath.node + path.parentPath.parentPath.node.left === path.parentPath.node && + path.parentPath.parentPath.get('right').isPure() ); } @@ -122,6 +114,15 @@ function remove(path) { } else if (isUnusedWildcard(path)) { remove(path.parentPath); } else if (!path.removed) { - path.remove(); + if ( + path.parentPath.isSequenceExpression() && + path.parent.expressions.length === 1 + ) { + // replace sequence expression with it's sole child + path.parentPath.replaceWith(path); + remove(path.parentPath); + } else { + path.remove(); + } } } From def2d49f633c1a5a2aefa7e7932efb2b9cb40063 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 6 May 2019 19:27:21 -0700 Subject: [PATCH 2/2] Update shake.js --- packages/core/parcel-bundler/src/scope-hoisting/shake.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/core/parcel-bundler/src/scope-hoisting/shake.js b/packages/core/parcel-bundler/src/scope-hoisting/shake.js index 6a22b18ebe6..f8bdc3e7712 100644 --- a/packages/core/parcel-bundler/src/scope-hoisting/shake.js +++ b/packages/core/parcel-bundler/src/scope-hoisting/shake.js @@ -76,8 +76,7 @@ function isExportAssignment(path) { // match "path.any = any;" path.parentPath.isMemberExpression() && path.parentPath.parentPath.isAssignmentExpression() && - path.parentPath.parentPath.node.left === path.parentPath.node && - path.parentPath.parentPath.get('right').isPure() + path.parentPath.parentPath.node.left === path.parentPath.node ); }