diff --git a/src/utils/chunkColouring.ts b/src/utils/chunkColouring.ts index 542a72aa2a6..86793db1739 100644 --- a/src/utils/chunkColouring.ts +++ b/src/utils/chunkColouring.ts @@ -1,134 +1,176 @@ +import ExternalModule from '../ExternalModule'; import Module from '../Module'; import { randomUint8Array, Uint8ArrayXor } from './entryHashing'; -function randomColour(): Uint8Array { - return randomUint8Array(10); -} - -function subset(small: Set, big: Set): boolean { - return small.size <= big.size && [...small].every(item => big.has(item)); -} - -interface StaticModuleGroup { - dynamicEntries: Set; - modules: Set; -} +type DependentModuleMap = Map>; export function assignChunkColouringHashes( entryModules: Module[], manualChunkModules: Record ) { - const colouredModules: Set = new Set(); - const staticModuleGroups: Map = new Map(); + const { dependentEntryPointsByModule, dynamicImportersByModule } = analyzeModuleGraph( + entryModules + ); + const dynamicDependentEntryPointsByDynamicEntry: DependentModuleMap = getDynamicDependentEntryPoints( + dependentEntryPointsByModule, + dynamicImportersByModule + ); - function collectStaticModuleGroup(rootModule: Module): StaticModuleGroup { - if (staticModuleGroups.has(rootModule)) { - return staticModuleGroups.get(rootModule)!; - } - const modules = new Set(); - const dynamicEntries = new Set(); - const group: StaticModuleGroup = { modules, dynamicEntries }; - staticModuleGroups.set(rootModule, group); - const process = (module: Module, importer: Module | null) => { - if (modules.has(module)) { - return; - } - modules.add(module); - if (!module.manualChunkAlias && importer?.manualChunkAlias) { - module.manualChunkAlias = importer.manualChunkAlias; - } - // TODO remove reverse? needed because previously manual chunk alias propogation was other way - for (const dependency of module.dependencies.slice().reverse()) { - if (dependency instanceof Module) { - process(dependency, module); - } - } - for (const { resolution } of module.dynamicImports) { - if (resolution instanceof Module && resolution.dynamicallyImportedBy.length > 0) { - dynamicEntries.add(resolution); - } + if (manualChunkModules) { + for (const chunkName of Object.keys(manualChunkModules)) { + const entryHash = randomUint8Array(10); + + for (const entry of manualChunkModules[chunkName]) { + addColourToModuleDependencies( + entry, + entryHash, + null, + dependentEntryPointsByModule, + dynamicDependentEntryPointsByDynamicEntry + ); } - }; - process(rootModule, null); - return group; + } } - function paintModules(inputEntryModules: Array<{ paint: Uint8Array; rootModule: Module }>): void { - const entryModules: Array<{ - loadedModules: Set; - paint: Uint8Array; - rootModule: Module; - }> = inputEntryModules.map(({ paint, rootModule }) => ({ - loadedModules: new Set(), - paint, - rootModule - })); + for (const entry of entryModules) { + if (!entry.manualChunkAlias) { + const entryHash = randomUint8Array(10); + addColourToModuleDependencies( + entry, + entryHash, + null, + dependentEntryPointsByModule, + dynamicDependentEntryPointsByDynamicEntry + ); + } + } - function registerNewEntryPoint( - rootModule: Module, - loadedModules: Set, - paint: Uint8Array - ): void { - const alreadyProcessed = entryModules.some( - entry => entry.rootModule === rootModule && subset(entry.loadedModules, loadedModules) + for (const entry of dynamicImportersByModule.keys()) { + if (!entry.manualChunkAlias) { + const entryHash = randomUint8Array(10); + addColourToModuleDependencies( + entry, + entryHash, + dynamicDependentEntryPointsByDynamicEntry.get(entry)!, + dependentEntryPointsByModule, + dynamicDependentEntryPointsByDynamicEntry ); - if (!alreadyProcessed) { - entryModules.push({ - loadedModules, - paint, - rootModule - }); - } } + } +} - function paintModule(rootModule: Module, loadedModules: Set, paint: Uint8Array): void { - const { modules, dynamicEntries } = collectStaticModuleGroup(rootModule); - const newLoadedModules = new Set([...loadedModules, ...modules]); - for (const module of modules) { - if (module.manualChunkAlias) { - if ( - !colouredModules.has(module) && - rootModule.manualChunkAlias === module.manualChunkAlias - ) { - Uint8ArrayXor(module.entryPointsHash, paint); - colouredModules.add(module); - } - } else { - if (!colouredModules.has(module) || !loadedModules.has(module)) { - Uint8ArrayXor(module.entryPointsHash, paint); - colouredModules.add(module); - } +function analyzeModuleGraph( + entryModules: Module[] +): { + dependentEntryPointsByModule: DependentModuleMap; + dynamicImportersByModule: DependentModuleMap; +} { + const dynamicImportersByModule: DependentModuleMap = new Map(); + const dependentEntryPointsByModule: DependentModuleMap = new Map(); + const entriesToHandle = new Set(entryModules); + for (const currentEntry of entriesToHandle) { + const modulesToHandle = new Set([currentEntry]); + for (const module of modulesToHandle) { + getDependentModules(dependentEntryPointsByModule, module).add(currentEntry); + for (const dependency of module.dependencies) { + if (!(dependency instanceof ExternalModule)) { + modulesToHandle.add(dependency); } } - for (const module of dynamicEntries) { - registerNewEntryPoint(module, newLoadedModules, randomColour()); + for (const { resolution } of module.dynamicImports) { + if ( + resolution instanceof Module && + resolution.dynamicallyImportedBy.length > 0 && + !resolution.manualChunkAlias + ) { + getDependentModules(dynamicImportersByModule, resolution).add(module); + entriesToHandle.add(resolution); + } } } - - for (let i = 0; i < entryModules.length /* updates */; i++) { - const { paint, rootModule, loadedModules } = entryModules[i]; - paintModule(rootModule, loadedModules, paint); - } } + return { dependentEntryPointsByModule, dynamicImportersByModule }; +} - const modules: Array<{ paint: Uint8Array; rootModule: Module }> = []; - - if (manualChunkModules) { - for (const chunkName of Object.keys(manualChunkModules)) { - const paint = randomColour(); +function getDependentModules(moduleMap: DependentModuleMap, module: Module): Set { + const dependentModules = moduleMap.get(module) || new Set(); + moduleMap.set(module, dependentModules); + return dependentModules; +} - for (const module of manualChunkModules[chunkName]) { - if (!module.manualChunkAlias) { - throw new Error('Missing manualChunkAlias'); - } - modules.push({ rootModule: module, paint }); +function getDynamicDependentEntryPoints( + dependentEntryPointsByModule: DependentModuleMap, + dynamicImportersByModule: DependentModuleMap +): DependentModuleMap { + const dynamicDependentEntryPointsByDynamicEntry: DependentModuleMap = new Map(); + for (const [dynamicEntry, importers] of dynamicImportersByModule.entries()) { + const dynamicDependentEntryPoints = getDependentModules( + dynamicDependentEntryPointsByDynamicEntry, + dynamicEntry + ); + for (const importer of importers) { + for (const entryPoint of dependentEntryPointsByModule.get(importer)!) { + dynamicDependentEntryPoints.add(entryPoint); } } } + return dynamicDependentEntryPointsByDynamicEntry; +} - for (const module of entryModules) { - modules.push({ rootModule: module, paint: randomColour() }); +function addColourToModuleDependencies( + entry: Module, + colour: Uint8Array, + dynamicDependentEntryPoints: Set | null, + dependentEntryPointsByModule: DependentModuleMap, + dynamicDependentEntryPointsByDynamicEntry: DependentModuleMap +) { + const manualChunkAlias = entry.manualChunkAlias; + const modulesToHandle = new Set([entry]); + for (const module of modulesToHandle) { + if (manualChunkAlias) { + module.manualChunkAlias = manualChunkAlias; + module.entryPointsHash = colour; + } else if ( + dynamicDependentEntryPoints && + areEntryPointsContainedOrDynamicallyDependent( + dynamicDependentEntryPoints, + dependentEntryPointsByModule.get(module)!, + dynamicDependentEntryPointsByDynamicEntry + ) + ) { + continue; + } else { + Uint8ArrayXor(module.entryPointsHash, colour); + } + for (const dependency of module.dependencies) { + if (!(dependency instanceof ExternalModule || dependency.manualChunkAlias)) { + modulesToHandle.add(dependency); + } + } } +} - paintModules(modules); +function areEntryPointsContainedOrDynamicallyDependent( + entryPoints: Set, + superSet: Set, + dynamicDependentEntryPointsByDynamicEntry: DependentModuleMap +): boolean { + for (const module of entryPoints) { + if (!superSet.has(module)) { + const dynamicDependentEntryPoints = dynamicDependentEntryPointsByDynamicEntry.get(module); + if ( + !( + dynamicDependentEntryPoints && + areEntryPointsContainedOrDynamicallyDependent( + dynamicDependentEntryPoints, + superSet, + dynamicDependentEntryPointsByDynamicEntry + ) + ) + ) { + return false; + } + } + } + return true; } diff --git a/src/utils/entryHashing.ts b/src/utils/entryHashing.ts index 5ab34274205..77327a7fd6e 100644 --- a/src/utils/entryHashing.ts +++ b/src/utils/entryHashing.ts @@ -25,9 +25,6 @@ export function randomUint8Array(len: number): Uint8Array { } export function Uint8ArrayXor(to: Uint8Array, from: Uint8Array): Uint8Array { - if (to.length !== from.length) { - throw new Error('Arrays are different sizes.'); - } for (let i = 0; i < to.length; i++) to[i] = to[i] ^ from[i]; return to; } diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/_config.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/_config.js new file mode 100644 index 00000000000..f475a15a739 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'inlines dynamic imports that are already statically imported' +}; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/_expected/amd/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/_expected/amd/main.js new file mode 100644 index 00000000000..3fab3918be6 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/_expected/amd/main.js @@ -0,0 +1,29 @@ +define(['exports'], function (exports) { 'use strict'; + + Promise.resolve().then(function () { return main; }).then(console.log); + console.log('dep1'); + const value1 = 'dep1'; + + var dep1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + value1: value1 + }); + + Promise.resolve().then(function () { return dep1; }).then(console.log); + console.log('dep2'); + const value2 = 'dep2'; + + Promise.resolve().then(function () { return main; }).then(console.log); + console.log('main', value1, value2); + const value = 'main'; + + var main = /*#__PURE__*/Object.freeze({ + __proto__: null, + value: value + }); + + exports.value = value; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/_expected/cjs/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/_expected/cjs/main.js new file mode 100644 index 00000000000..cb766ee459d --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/_expected/cjs/main.js @@ -0,0 +1,27 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +Promise.resolve().then(function () { return main; }).then(console.log); +console.log('dep1'); +const value1 = 'dep1'; + +var dep1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + value1: value1 +}); + +Promise.resolve().then(function () { return dep1; }).then(console.log); +console.log('dep2'); +const value2 = 'dep2'; + +Promise.resolve().then(function () { return main; }).then(console.log); +console.log('main', value1, value2); +const value = 'main'; + +var main = /*#__PURE__*/Object.freeze({ + __proto__: null, + value: value +}); + +exports.value = value; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/_expected/es/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/_expected/es/main.js new file mode 100644 index 00000000000..ab2781aef36 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/_expected/es/main.js @@ -0,0 +1,23 @@ +Promise.resolve().then(function () { return main; }).then(console.log); +console.log('dep1'); +const value1 = 'dep1'; + +var dep1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + value1: value1 +}); + +Promise.resolve().then(function () { return dep1; }).then(console.log); +console.log('dep2'); +const value2 = 'dep2'; + +Promise.resolve().then(function () { return main; }).then(console.log); +console.log('main', value1, value2); +const value = 'main'; + +var main = /*#__PURE__*/Object.freeze({ + __proto__: null, + value: value +}); + +export { value }; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/_expected/system/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/_expected/system/main.js new file mode 100644 index 00000000000..30ad2f5698f --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/_expected/system/main.js @@ -0,0 +1,30 @@ +System.register([], function (exports) { + 'use strict'; + return { + execute: function () { + + Promise.resolve().then(function () { return main; }).then(console.log); + console.log('dep1'); + const value1 = 'dep1'; + + var dep1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + value1: value1 + }); + + Promise.resolve().then(function () { return dep1; }).then(console.log); + console.log('dep2'); + const value2 = 'dep2'; + + Promise.resolve().then(function () { return main; }).then(console.log); + console.log('main', value1, value2); + const value = exports('value', 'main'); + + var main = /*#__PURE__*/Object.freeze({ + __proto__: null, + value: value + }); + + } + }; +}); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/dep1.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/dep1.js new file mode 100644 index 00000000000..5396c9c53d3 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/dep1.js @@ -0,0 +1,3 @@ +import('./main.js').then(console.log); +console.log('dep1'); +export const value1 = 'dep1'; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/dep2.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/dep2.js new file mode 100644 index 00000000000..8bcaf7e8992 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/dep2.js @@ -0,0 +1,3 @@ +import('./dep1.js').then(console.log); +console.log('dep2'); +export const value2 = 'dep2'; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/main.js new file mode 100644 index 00000000000..d8091f19910 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-1/main.js @@ -0,0 +1,6 @@ +import { value1 } from './dep1.js'; +import { value2 } from './dep2.js'; + +import('./main.js').then(console.log); +console.log('main', value1, value2); +export const value = 'main'; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/_config.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/_config.js new file mode 100644 index 00000000000..8fb4c32176c --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'inlines dynamic imports that are already statically imported by their importers' +}; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/_expected/amd/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/_expected/amd/main.js new file mode 100644 index 00000000000..466b0dabc88 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/_expected/amd/main.js @@ -0,0 +1,23 @@ +define(function () { 'use strict'; + + Promise.resolve().then(function () { return dynamic2; }).then(console.log); + console.log('dynamic1'); + const value1 = 'dynamic1'; + + var dynamic1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + value1: value1 + }); + + console.log('dynamic2'); + const value2 = 'dynamic2'; + + var dynamic2 = /*#__PURE__*/Object.freeze({ + __proto__: null, + value2: value2 + }); + + Promise.resolve().then(function () { return dynamic1; }).then(console.log); + console.log('main', value1, value2); + +}); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/_expected/cjs/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/_expected/cjs/main.js new file mode 100644 index 00000000000..5b5e7618221 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/_expected/cjs/main.js @@ -0,0 +1,21 @@ +'use strict'; + +Promise.resolve().then(function () { return dynamic2; }).then(console.log); +console.log('dynamic1'); +const value1 = 'dynamic1'; + +var dynamic1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + value1: value1 +}); + +console.log('dynamic2'); +const value2 = 'dynamic2'; + +var dynamic2 = /*#__PURE__*/Object.freeze({ + __proto__: null, + value2: value2 +}); + +Promise.resolve().then(function () { return dynamic1; }).then(console.log); +console.log('main', value1, value2); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/_expected/es/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/_expected/es/main.js new file mode 100644 index 00000000000..d5bed32b8dc --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/_expected/es/main.js @@ -0,0 +1,19 @@ +Promise.resolve().then(function () { return dynamic2; }).then(console.log); +console.log('dynamic1'); +const value1 = 'dynamic1'; + +var dynamic1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + value1: value1 +}); + +console.log('dynamic2'); +const value2 = 'dynamic2'; + +var dynamic2 = /*#__PURE__*/Object.freeze({ + __proto__: null, + value2: value2 +}); + +Promise.resolve().then(function () { return dynamic1; }).then(console.log); +console.log('main', value1, value2); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/_expected/system/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/_expected/system/main.js new file mode 100644 index 00000000000..35382e9f21f --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/_expected/system/main.js @@ -0,0 +1,28 @@ +System.register([], function () { + 'use strict'; + return { + execute: function () { + + Promise.resolve().then(function () { return dynamic2; }).then(console.log); + console.log('dynamic1'); + const value1 = 'dynamic1'; + + var dynamic1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + value1: value1 + }); + + console.log('dynamic2'); + const value2 = 'dynamic2'; + + var dynamic2 = /*#__PURE__*/Object.freeze({ + __proto__: null, + value2: value2 + }); + + Promise.resolve().then(function () { return dynamic1; }).then(console.log); + console.log('main', value1, value2); + + } + }; +}); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/dynamic1.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/dynamic1.js new file mode 100644 index 00000000000..fb728362620 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/dynamic1.js @@ -0,0 +1,3 @@ +import('./dynamic2.js').then(console.log); +console.log('dynamic1'); +export const value1 = 'dynamic1'; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/dynamic2.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/dynamic2.js new file mode 100644 index 00000000000..d99f0e75577 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/dynamic2.js @@ -0,0 +1,2 @@ +console.log('dynamic2'); +export const value2 = 'dynamic2'; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/main.js new file mode 100644 index 00000000000..5fccea310d3 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-already-contained-2/main.js @@ -0,0 +1,5 @@ +import { value1 } from './dynamic1.js'; +import { value2 } from './dynamic2.js'; + +import('./dynamic1.js').then(console.log); +console.log('main', value1, value2); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_config.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_config.js new file mode 100644 index 00000000000..d8b7a769273 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'handles if a dynamically imported module imports another module dynamically' +}; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/amd/generated-dynamic1.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/amd/generated-dynamic1.js new file mode 100644 index 00000000000..41b95d106c9 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/amd/generated-dynamic1.js @@ -0,0 +1,5 @@ +define(['require'], function (require) { 'use strict'; + + new Promise(function (resolve, reject) { require(['./generated-dynamic2'], resolve, reject) }); + +}); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/amd/generated-dynamic2.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/amd/generated-dynamic2.js new file mode 100644 index 00000000000..b30754a60e8 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/amd/generated-dynamic2.js @@ -0,0 +1,7 @@ +define(['exports', './main'], function (exports, main) { 'use strict'; + + console.log('dynamic2', main.value); + + exports.value = main.value; + +}); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/amd/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/amd/main.js new file mode 100644 index 00000000000..1cc193e37b7 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/amd/main.js @@ -0,0 +1,12 @@ +define(['require', 'exports'], function (require, exports) { 'use strict'; + + const value = 'shared'; + + console.log('dynamic1', value); + new Promise(function (resolve, reject) { require(['./generated-dynamic1'], resolve, reject) }); + + exports.value = value; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/cjs/generated-dynamic1.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/cjs/generated-dynamic1.js new file mode 100644 index 00000000000..14c1997bdbb --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/cjs/generated-dynamic1.js @@ -0,0 +1,3 @@ +'use strict'; + +new Promise(function (resolve) { resolve(require('./generated-dynamic2.js')); }); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/cjs/generated-dynamic2.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/cjs/generated-dynamic2.js new file mode 100644 index 00000000000..ae613ed0e60 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/cjs/generated-dynamic2.js @@ -0,0 +1,7 @@ +'use strict'; + +var main = require('./main.js'); + +console.log('dynamic2', main.value); + +exports.value = main.value; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/cjs/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/cjs/main.js new file mode 100644 index 00000000000..3eb9d321be8 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/cjs/main.js @@ -0,0 +1,10 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +const value = 'shared'; + +console.log('dynamic1', value); +new Promise(function (resolve) { resolve(require('./generated-dynamic1.js')); }); + +exports.value = value; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/es/generated-dynamic1.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/es/generated-dynamic1.js new file mode 100644 index 00000000000..45c226aa4a3 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/es/generated-dynamic1.js @@ -0,0 +1 @@ +import('./generated-dynamic2.js'); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/es/generated-dynamic2.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/es/generated-dynamic2.js new file mode 100644 index 00000000000..5b29c49b1a7 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/es/generated-dynamic2.js @@ -0,0 +1,5 @@ +import { value } from './main.js'; + +export { value } from './main.js'; + +console.log('dynamic2', value); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/es/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/es/main.js new file mode 100644 index 00000000000..a140614b88c --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/es/main.js @@ -0,0 +1,6 @@ +const value = 'shared'; + +console.log('dynamic1', value); +import('./generated-dynamic1.js'); + +export { value }; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/system/generated-dynamic1.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/system/generated-dynamic1.js new file mode 100644 index 00000000000..0d19e5aa49b --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/system/generated-dynamic1.js @@ -0,0 +1,10 @@ +System.register([], function (exports, module) { + 'use strict'; + return { + execute: function () { + + module.import('./generated-dynamic2.js'); + + } + }; +}); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/system/generated-dynamic2.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/system/generated-dynamic2.js new file mode 100644 index 00000000000..5bb722682d3 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/system/generated-dynamic2.js @@ -0,0 +1,15 @@ +System.register(['./main.js'], function (exports) { + 'use strict'; + var value; + return { + setters: [function (module) { + value = module.value; + exports('value', module.value); + }], + execute: function () { + + console.log('dynamic2', value); + + } + }; +}); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/system/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/system/main.js new file mode 100644 index 00000000000..fa1f161107b --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/_expected/system/main.js @@ -0,0 +1,13 @@ +System.register([], function (exports, module) { + 'use strict'; + return { + execute: function () { + + const value = exports('value', 'shared'); + + console.log('dynamic1', value); + module.import('./generated-dynamic1.js'); + + } + }; +}); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/dep.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/dep.js new file mode 100644 index 00000000000..1d4be9c15d0 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/dep.js @@ -0,0 +1 @@ +export const value = 'shared'; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/dynamic1.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/dynamic1.js new file mode 100644 index 00000000000..ff23cb6b9eb --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/dynamic1.js @@ -0,0 +1 @@ +import('./dynamic2.js'); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/dynamic2.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/dynamic2.js new file mode 100644 index 00000000000..04fadf2d7da --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/dynamic2.js @@ -0,0 +1,4 @@ +import { value } from './dep.js'; + +console.log('dynamic2', value); +export { value }; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/main.js new file mode 100644 index 00000000000..e7836b4b69a --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic-multi-stage/main.js @@ -0,0 +1,5 @@ +import { value } from './dep.js'; + +console.log('dynamic1', value); +import('./dynamic1.js'); +export { value }; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_config.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_config.js new file mode 100644 index 00000000000..d8b7a769273 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'handles if a dynamically imported module imports another module dynamically' +}; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/amd/generated-dynamic1.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/amd/generated-dynamic1.js new file mode 100644 index 00000000000..50a4863d1b2 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/amd/generated-dynamic1.js @@ -0,0 +1,10 @@ +define(['require', 'exports'], function (require, exports) { 'use strict'; + + const value = 'shared'; + + console.log('dynamic1', value); + new Promise(function (resolve, reject) { require(['./generated-dynamic2'], resolve, reject) }); + + exports.value = value; + +}); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/amd/generated-dynamic2.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/amd/generated-dynamic2.js new file mode 100644 index 00000000000..b43d0ad04a5 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/amd/generated-dynamic2.js @@ -0,0 +1,7 @@ +define(['exports', './generated-dynamic1'], function (exports, dynamic1) { 'use strict'; + + console.log('dynamic2', dynamic1.value); + + exports.value = dynamic1.value; + +}); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/amd/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/amd/main.js new file mode 100644 index 00000000000..935d1692f83 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/amd/main.js @@ -0,0 +1,5 @@ +define(['require'], function (require) { 'use strict'; + + new Promise(function (resolve, reject) { require(['./generated-dynamic1'], resolve, reject) }); + +}); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/cjs/generated-dynamic1.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/cjs/generated-dynamic1.js new file mode 100644 index 00000000000..a7b3ae53ddb --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/cjs/generated-dynamic1.js @@ -0,0 +1,8 @@ +'use strict'; + +const value = 'shared'; + +console.log('dynamic1', value); +new Promise(function (resolve) { resolve(require('./generated-dynamic2.js')); }); + +exports.value = value; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/cjs/generated-dynamic2.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/cjs/generated-dynamic2.js new file mode 100644 index 00000000000..35685a35ed6 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/cjs/generated-dynamic2.js @@ -0,0 +1,7 @@ +'use strict'; + +var dynamic1 = require('./generated-dynamic1.js'); + +console.log('dynamic2', dynamic1.value); + +exports.value = dynamic1.value; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/cjs/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/cjs/main.js new file mode 100644 index 00000000000..85605bbd0a6 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/cjs/main.js @@ -0,0 +1,3 @@ +'use strict'; + +new Promise(function (resolve) { resolve(require('./generated-dynamic1.js')); }); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/es/generated-dynamic1.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/es/generated-dynamic1.js new file mode 100644 index 00000000000..5876ac36d26 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/es/generated-dynamic1.js @@ -0,0 +1,6 @@ +const value = 'shared'; + +console.log('dynamic1', value); +import('./generated-dynamic2.js'); + +export { value }; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/es/generated-dynamic2.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/es/generated-dynamic2.js new file mode 100644 index 00000000000..56a22dce8d1 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/es/generated-dynamic2.js @@ -0,0 +1,5 @@ +import { value } from './generated-dynamic1.js'; + +export { value } from './generated-dynamic1.js'; + +console.log('dynamic2', value); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/es/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/es/main.js new file mode 100644 index 00000000000..b46872a8428 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/es/main.js @@ -0,0 +1 @@ +import('./generated-dynamic1.js'); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/system/generated-dynamic1.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/system/generated-dynamic1.js new file mode 100644 index 00000000000..2730357cfe2 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/system/generated-dynamic1.js @@ -0,0 +1,13 @@ +System.register([], function (exports, module) { + 'use strict'; + return { + execute: function () { + + const value = exports('value', 'shared'); + + console.log('dynamic1', value); + module.import('./generated-dynamic2.js'); + + } + }; +}); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/system/generated-dynamic2.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/system/generated-dynamic2.js new file mode 100644 index 00000000000..934231e63ce --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/system/generated-dynamic2.js @@ -0,0 +1,15 @@ +System.register(['./generated-dynamic1.js'], function (exports) { + 'use strict'; + var value; + return { + setters: [function (module) { + value = module.value; + exports('value', module.value); + }], + execute: function () { + + console.log('dynamic2', value); + + } + }; +}); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/system/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/system/main.js new file mode 100644 index 00000000000..6bf031d4fed --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/_expected/system/main.js @@ -0,0 +1,10 @@ +System.register([], function (exports, module) { + 'use strict'; + return { + execute: function () { + + module.import('./generated-dynamic1.js'); + + } + }; +}); diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/dep.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/dep.js new file mode 100644 index 00000000000..1d4be9c15d0 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/dep.js @@ -0,0 +1 @@ +export const value = 'shared'; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/dynamic1.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/dynamic1.js new file mode 100644 index 00000000000..481d1476ae5 --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/dynamic1.js @@ -0,0 +1,5 @@ +import { value } from './dep.js'; + +console.log('dynamic1', value); +import('./dynamic2.js'); +export { value }; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/dynamic2.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/dynamic2.js new file mode 100644 index 00000000000..04fadf2d7da --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/dynamic2.js @@ -0,0 +1,4 @@ +import { value } from './dep.js'; + +console.log('dynamic2', value); +export { value }; diff --git a/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/main.js b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/main.js new file mode 100644 index 00000000000..587eba57a0b --- /dev/null +++ b/test/chunking-form/samples/improved-dynamic-chunks/dynamic-import-dynamic/main.js @@ -0,0 +1 @@ +import('./dynamic1.js'); diff --git a/test/watch/index.js b/test/watch/index.js index 1a173604177..f454536bdd9 100644 --- a/test/watch/index.js +++ b/test/watch/index.js @@ -844,8 +844,8 @@ describe('rollup.watch', () => { // this should only update the hash of that particular entry point sander.writeFileSync( - 'test/_tmp/input/main-dynamic.js', - "export default import('./shared')\nconsole.log('main-dynamic')" + 'test/_tmp/input/main-static.js', + "import {value} from './shared';\nexport default 2 * value;" ); }, 'START', @@ -857,8 +857,8 @@ describe('rollup.watch', () => { .readdirSync('test/_tmp/output') .sort(); sander.rimrafSync('test/_tmp/output'); - assert.strictEqual(newStaticName, staticName); - assert.notEqual(newDynamicName, dynamicName); + assert.notEqual(newStaticName, staticName); + assert.strictEqual(newDynamicName, dynamicName); assert.strictEqual(newChunkName, chunkName); staticName = newStaticName;