From 297cc8c6d4b65e1624a6cea3c864601d91d7561e Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Tue, 26 Feb 2019 06:52:30 +0100 Subject: [PATCH] Deduplicate imports referencing default exports and their original variables (#2719) * Deduplicate imports referencing default exports and their original variables * Update changelog --- CHANGELOG.md | 9 ++++++ src/Chunk.ts | 31 ++++++++++++------- src/ast/variables/ExportDefaultVariable.ts | 4 +++ .../_config.js | 7 +++++ .../_expected/amd/generated-chunk.js | 8 +++++ .../_expected/amd/main1.js | 5 +++ .../_expected/amd/main2.js | 5 +++ .../_expected/cjs/generated-chunk.js | 6 ++++ .../_expected/cjs/main1.js | 5 +++ .../_expected/cjs/main2.js | 5 +++ .../_expected/es/generated-chunk.js | 3 ++ .../_expected/es/main1.js | 3 ++ .../_expected/es/main2.js | 3 ++ .../_expected/system/generated-chunk.js | 12 +++++++ .../_expected/system/main1.js | 14 +++++++++ .../_expected/system/main2.js | 14 +++++++++ .../foo.js | 1 + .../main1.js | 4 +++ .../main2.js | 4 +++ .../proxy.js | 2 ++ 20 files changed, 133 insertions(+), 12 deletions(-) create mode 100644 test/chunking-form/samples/deduplicate-imports-referencing-originals/_config.js create mode 100644 test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/amd/generated-chunk.js create mode 100644 test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/amd/main1.js create mode 100644 test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/amd/main2.js create mode 100644 test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/cjs/generated-chunk.js create mode 100644 test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/cjs/main1.js create mode 100644 test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/cjs/main2.js create mode 100644 test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/es/generated-chunk.js create mode 100644 test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/es/main1.js create mode 100644 test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/es/main2.js create mode 100644 test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/system/generated-chunk.js create mode 100644 test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/system/main1.js create mode 100644 test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/system/main2.js create mode 100644 test/chunking-form/samples/deduplicate-imports-referencing-originals/foo.js create mode 100644 test/chunking-form/samples/deduplicate-imports-referencing-originals/main1.js create mode 100644 test/chunking-form/samples/deduplicate-imports-referencing-originals/main2.js create mode 100644 test/chunking-form/samples/deduplicate-imports-referencing-originals/proxy.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 7aa6f02d134..acda6cbb2fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # rollup changelog +## 1.2.4 +*2019-02-25* + +### Bug Fixes +* Fix an issue where a variable was imported twice under the same name (#2715) + +### Pull Requests +* [#2715](https://github.com/rollup/rollup/pull/2715): Deduplicate imports referencing default exports and their original variables (@lukastaegert) + ## 1.2.3 *2019-02-23* diff --git a/src/Chunk.ts b/src/Chunk.ts index 11dd98f1da5..b9ee6619f57 100644 --- a/src/Chunk.ts +++ b/src/Chunk.ts @@ -2,7 +2,9 @@ import sha256 from 'hash.js/lib/hash/sha/256'; import MagicString, { Bundle as MagicStringBundle, SourceMap } from 'magic-string'; import * as NodeType from './ast/nodes/NodeType'; import { UNDEFINED_EXPRESSION } from './ast/values'; -import { isExportDefaultVariable } from './ast/variables/ExportDefaultVariable'; +import ExportDefaultVariable, { + isExportDefaultVariable +} from './ast/variables/ExportDefaultVariable'; import ExportShimVariable from './ast/variables/ExportShimVariable'; import GlobalVariable from './ast/variables/GlobalVariable'; import LocalVariable from './ast/variables/LocalVariable'; @@ -478,17 +480,22 @@ export default class Chunk { exportDeclaration.push({ imported: importName, reexported: exportName }); } + const importsAsArray = Array.from(this.imports); const dependencies: ChunkDependencies = []; - this.dependencies.forEach(dep => { - const importsFromDependency = Array.from(this.imports).filter(variable => - variable.module instanceof Module ? variable.module.chunk === dep : variable.module === dep - ); - - let imports: ImportSpecifier[]; - if (importsFromDependency.length) { - imports = []; - for (const variable of importsFromDependency) { + for (const dep of this.dependencies) { + const imports: ImportSpecifier[] = []; + for (const variable of importsAsArray) { + if ( + (variable.module instanceof Module + ? variable.module.chunk === dep + : variable.module === dep) && + !( + variable instanceof ExportDefaultVariable && + variable.referencesOriginal() && + this.imports.has(variable.getOriginalVariable()) + ) + ) { const local = variable.getName(); const imported = variable.module instanceof ExternalModule @@ -534,9 +541,9 @@ export default class Chunk { exportsNames, exportsDefault, reexports, - imports + imports: imports.length > 0 ? imports : null }); - }); + } return dependencies; } diff --git a/src/ast/variables/ExportDefaultVariable.ts b/src/ast/variables/ExportDefaultVariable.ts index 60060f749f2..96fdccbc46f 100644 --- a/src/ast/variables/ExportDefaultVariable.ts +++ b/src/ast/variables/ExportDefaultVariable.ts @@ -47,6 +47,10 @@ export default class ExportDefaultVariable extends LocalVariable { return this.referencesOriginal() ? this.originalId.variable.getName() : super.getName(); } + getOriginalVariable(): Variable | null { + return (this.originalId && this.originalId.variable) || null; + } + getOriginalVariableName(): string | null { return (this.originalId && this.originalId.name) || null; } diff --git a/test/chunking-form/samples/deduplicate-imports-referencing-originals/_config.js b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_config.js new file mode 100644 index 00000000000..8bf09102383 --- /dev/null +++ b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_config.js @@ -0,0 +1,7 @@ +module.exports = { + description: + 'do not import variables that reference an original if the original is already imported', + options: { + input: ['main1', 'main2'] + } +}; diff --git a/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/amd/generated-chunk.js b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/amd/generated-chunk.js new file mode 100644 index 00000000000..a142f34df0d --- /dev/null +++ b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/amd/generated-chunk.js @@ -0,0 +1,8 @@ +define(['exports'], function (exports) { 'use strict'; + + const foo = {}; + + exports.foo = foo; + exports.bar = foo; + +}); diff --git a/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/amd/main1.js b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/amd/main1.js new file mode 100644 index 00000000000..302e4c4da46 --- /dev/null +++ b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/amd/main1.js @@ -0,0 +1,5 @@ +define(['./generated-chunk.js'], function (__chunk_1) { 'use strict'; + + console.log(__chunk_1.bar, __chunk_1.bar); + +}); diff --git a/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/amd/main2.js b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/amd/main2.js new file mode 100644 index 00000000000..302e4c4da46 --- /dev/null +++ b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/amd/main2.js @@ -0,0 +1,5 @@ +define(['./generated-chunk.js'], function (__chunk_1) { 'use strict'; + + console.log(__chunk_1.bar, __chunk_1.bar); + +}); diff --git a/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/cjs/generated-chunk.js b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/cjs/generated-chunk.js new file mode 100644 index 00000000000..a76e69f06f0 --- /dev/null +++ b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/cjs/generated-chunk.js @@ -0,0 +1,6 @@ +'use strict'; + +const foo = {}; + +exports.foo = foo; +exports.bar = foo; diff --git a/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/cjs/main1.js b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/cjs/main1.js new file mode 100644 index 00000000000..b3cc08fc4d9 --- /dev/null +++ b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/cjs/main1.js @@ -0,0 +1,5 @@ +'use strict'; + +var __chunk_1 = require('./generated-chunk.js'); + +console.log(__chunk_1.bar, __chunk_1.bar); diff --git a/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/cjs/main2.js b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/cjs/main2.js new file mode 100644 index 00000000000..b3cc08fc4d9 --- /dev/null +++ b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/cjs/main2.js @@ -0,0 +1,5 @@ +'use strict'; + +var __chunk_1 = require('./generated-chunk.js'); + +console.log(__chunk_1.bar, __chunk_1.bar); diff --git a/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/es/generated-chunk.js b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/es/generated-chunk.js new file mode 100644 index 00000000000..1127b4cd6fa --- /dev/null +++ b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/es/generated-chunk.js @@ -0,0 +1,3 @@ +const foo = {}; + +export { foo as a, foo as b }; diff --git a/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/es/main1.js b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/es/main1.js new file mode 100644 index 00000000000..9b81ff8ea20 --- /dev/null +++ b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/es/main1.js @@ -0,0 +1,3 @@ +import { a as bar } from './generated-chunk.js'; + +console.log(bar, bar); diff --git a/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/es/main2.js b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/es/main2.js new file mode 100644 index 00000000000..9b81ff8ea20 --- /dev/null +++ b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/es/main2.js @@ -0,0 +1,3 @@ +import { a as bar } from './generated-chunk.js'; + +console.log(bar, bar); diff --git a/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/system/generated-chunk.js b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/system/generated-chunk.js new file mode 100644 index 00000000000..5036f5bcd91 --- /dev/null +++ b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/system/generated-chunk.js @@ -0,0 +1,12 @@ +System.register([], function (exports, module) { + 'use strict'; + return { + execute: function () { + + const foo = exports('a', {}); + + exports('b', foo); + + } + }; +}); diff --git a/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/system/main1.js b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/system/main1.js new file mode 100644 index 00000000000..01df6b33d3c --- /dev/null +++ b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/system/main1.js @@ -0,0 +1,14 @@ +System.register(['./generated-chunk.js'], function (exports, module) { + 'use strict'; + var bar; + return { + setters: [function (module) { + bar = module.a; + }], + execute: function () { + + console.log(bar, bar); + + } + }; +}); diff --git a/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/system/main2.js b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/system/main2.js new file mode 100644 index 00000000000..01df6b33d3c --- /dev/null +++ b/test/chunking-form/samples/deduplicate-imports-referencing-originals/_expected/system/main2.js @@ -0,0 +1,14 @@ +System.register(['./generated-chunk.js'], function (exports, module) { + 'use strict'; + var bar; + return { + setters: [function (module) { + bar = module.a; + }], + execute: function () { + + console.log(bar, bar); + + } + }; +}); diff --git a/test/chunking-form/samples/deduplicate-imports-referencing-originals/foo.js b/test/chunking-form/samples/deduplicate-imports-referencing-originals/foo.js new file mode 100644 index 00000000000..71658c1342b --- /dev/null +++ b/test/chunking-form/samples/deduplicate-imports-referencing-originals/foo.js @@ -0,0 +1 @@ +export const foo = {}; diff --git a/test/chunking-form/samples/deduplicate-imports-referencing-originals/main1.js b/test/chunking-form/samples/deduplicate-imports-referencing-originals/main1.js new file mode 100644 index 00000000000..ef4eee4f8d5 --- /dev/null +++ b/test/chunking-form/samples/deduplicate-imports-referencing-originals/main1.js @@ -0,0 +1,4 @@ +import { foo } from './foo'; +import bar from './proxy'; + +console.log(foo, bar); diff --git a/test/chunking-form/samples/deduplicate-imports-referencing-originals/main2.js b/test/chunking-form/samples/deduplicate-imports-referencing-originals/main2.js new file mode 100644 index 00000000000..ef4eee4f8d5 --- /dev/null +++ b/test/chunking-form/samples/deduplicate-imports-referencing-originals/main2.js @@ -0,0 +1,4 @@ +import { foo } from './foo'; +import bar from './proxy'; + +console.log(foo, bar); diff --git a/test/chunking-form/samples/deduplicate-imports-referencing-originals/proxy.js b/test/chunking-form/samples/deduplicate-imports-referencing-originals/proxy.js new file mode 100644 index 00000000000..8df5c60f1f6 --- /dev/null +++ b/test/chunking-form/samples/deduplicate-imports-referencing-originals/proxy.js @@ -0,0 +1,2 @@ +import { foo } from './foo'; +export default foo;