diff --git a/src/Chunk.ts b/src/Chunk.ts index bf621090a40..a2492d8ca97 100644 --- a/src/Chunk.ts +++ b/src/Chunk.ts @@ -895,8 +895,7 @@ export default class Chunk { } else { const variable = this.exportsByName![exportName]; if (variable instanceof SyntheticNamedExportVariable) continue; - const module = variable.module; - if (!module) continue; + const module = variable.module!; if (module instanceof Module) { exportChunk = this.chunkByModule.get(module)!; if (exportChunk === this) continue; @@ -1146,16 +1145,14 @@ export default class Chunk { if (variable instanceof SyntheticNamedExportVariable) { variable = variable.getBaseVariable(); } - if (variable.module) { - const chunk = this.chunkByModule.get(variable.module as Module); - if (chunk !== this) { - this.imports.add(variable); - if ( - !(variable instanceof NamespaceVariable && this.outputOptions.preserveModules) && - variable.module instanceof Module - ) { - chunk!.exports.add(variable); - } + const chunk = this.chunkByModule.get(variable.module as Module); + if (chunk !== this) { + this.imports.add(variable); + if ( + !(variable instanceof NamespaceVariable && this.outputOptions.preserveModules) && + variable.module instanceof Module + ) { + chunk!.exports.add(variable); } } } diff --git a/src/Module.ts b/src/Module.ts index a88cf041bc9..da9eac2d129 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -846,9 +846,11 @@ export default class Module { private addLocationToLogProps(props: RollupLogProps, pos: number): void { props.id = this.id; props.pos = pos; - let { column, line } = locate(this.code, pos, { offsetLine: 1 }); + let code = this.code; + let { column, line } = locate(code, pos, { offsetLine: 1 }); try { ({ column, line } = getOriginalLocation(this.sourcemapChain, { column, line })); + code = this.originalCode; } catch (e) { this.options.onwarn({ code: 'SOURCEMAP_ERROR', @@ -862,7 +864,7 @@ export default class Module { pos }); } - augmentCodeLocation(props, { column, line }, this.originalCode, this.id); + augmentCodeLocation(props, { column, line }, code, this.id); } private addModulesToImportDescriptions(importDescription: { diff --git a/src/utils/chunkAssignment.ts b/src/utils/chunkAssignment.ts index 186cc895ddf..e386ebb7ca8 100644 --- a/src/utils/chunkAssignment.ts +++ b/src/utils/chunkAssignment.ts @@ -21,10 +21,7 @@ export function getChunkAssignments( } const assignedEntryPointsByModule: DependentModuleMap = new Map(); - const { dependentEntryPointsByModule, dynamicEntryModules } = analyzeModuleGraph( - entryModules, - modulesInManualChunks - ); + const { dependentEntryPointsByModule, dynamicEntryModules } = analyzeModuleGraph(entryModules); const dynamicallyDependentEntryPointsByDynamicEntry: DependentModuleMap = getDynamicDependentEntryPoints( dependentEntryPointsByModule, dynamicEntryModules @@ -59,16 +56,16 @@ export function getChunkAssignments( function areEntryPointsContainedOrDynamicallyDependent( entryPoints: Set, - superSet: Set + containedIn: Set ): boolean { const entriesToCheck = new Set(entryPoints); for (const entry of entriesToCheck) { - if (!superSet.has(entry)) { + if (!containedIn.has(entry)) { if (staticEntries.has(entry)) return false; - const dynamicDependentEntryPoints = dynamicallyDependentEntryPointsByDynamicEntry.get( + const dynamicallyDependentEntryPoints = dynamicallyDependentEntryPointsByDynamicEntry.get( entry )!; - for (const dependentEntry of dynamicDependentEntryPoints) { + for (const dependentEntry of dynamicallyDependentEntryPoints) { entriesToCheck.add(dependentEntry); } } @@ -115,8 +112,7 @@ function addStaticDependenciesToManualChunk( } function analyzeModuleGraph( - entryModules: Module[], - modulesInManualChunks: Set + entryModules: Module[] ): { dependentEntryPointsByModule: DependentModuleMap; dynamicEntryModules: Set; @@ -134,20 +130,14 @@ function analyzeModuleGraph( } } for (const { resolution } of module.dynamicImports) { - if ( - resolution instanceof Module && - resolution.includedDynamicImporters.length > 0 && - !modulesInManualChunks.has(resolution) - ) { + if (resolution instanceof Module && resolution.includedDynamicImporters.length > 0) { dynamicEntryModules.add(resolution); entriesToHandle.add(resolution); } } for (const dependency of module.implicitlyLoadedBefore) { - if (!modulesInManualChunks.has(dependency)) { - dynamicEntryModules.add(dependency); - entriesToHandle.add(dependency); - } + dynamicEntryModules.add(dependency); + entriesToHandle.add(dependency); } } } diff --git a/test/form/samples/custom-module-context-function/_config.js b/test/form/samples/custom-module-context-function/_config.js index e42a80b2638..c10efdfacbe 100644 --- a/test/form/samples/custom-module-context-function/_config.js +++ b/test/form/samples/custom-module-context-function/_config.js @@ -3,7 +3,12 @@ module.exports = { expectedWarnings: ['THIS_IS_UNDEFINED'], options: { moduleContext(id) { - return /main\.js$/.test(id) ? 'lolwut' : 'undefined'; + if (id.endsWith('main.js')) { + return 'window'; + } + if (id.endsWith('foo.js')) { + return 'global'; + } } } }; diff --git a/test/form/samples/custom-module-context-function/_expected.js b/test/form/samples/custom-module-context-function/_expected.js new file mode 100644 index 00000000000..c4918f43758 --- /dev/null +++ b/test/form/samples/custom-module-context-function/_expected.js @@ -0,0 +1,5 @@ +global.prop = 'foo'; + +undefined.prop = 'bar'; + +window.prop = 'main'; diff --git a/test/form/samples/custom-module-context-function/_expected/amd.js b/test/form/samples/custom-module-context-function/_expected/amd.js deleted file mode 100644 index 92747997ff2..00000000000 --- a/test/form/samples/custom-module-context-function/_expected/amd.js +++ /dev/null @@ -1,7 +0,0 @@ -define(function () { 'use strict'; - - undefined.prop = 'nope'; - - lolwut.prop = '???'; - -}); diff --git a/test/form/samples/custom-module-context-function/_expected/cjs.js b/test/form/samples/custom-module-context-function/_expected/cjs.js deleted file mode 100644 index 35a5b08d3a9..00000000000 --- a/test/form/samples/custom-module-context-function/_expected/cjs.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -undefined.prop = 'nope'; - -lolwut.prop = '???'; diff --git a/test/form/samples/custom-module-context-function/_expected/es.js b/test/form/samples/custom-module-context-function/_expected/es.js deleted file mode 100644 index a6903e00c89..00000000000 --- a/test/form/samples/custom-module-context-function/_expected/es.js +++ /dev/null @@ -1,3 +0,0 @@ -undefined.prop = 'nope'; - -lolwut.prop = '???'; diff --git a/test/form/samples/custom-module-context-function/_expected/iife.js b/test/form/samples/custom-module-context-function/_expected/iife.js deleted file mode 100644 index 7926fe6e7ea..00000000000 --- a/test/form/samples/custom-module-context-function/_expected/iife.js +++ /dev/null @@ -1,8 +0,0 @@ -(function () { - 'use strict'; - - undefined.prop = 'nope'; - - lolwut.prop = '???'; - -}()); diff --git a/test/form/samples/custom-module-context-function/_expected/system.js b/test/form/samples/custom-module-context-function/_expected/system.js deleted file mode 100644 index 1e323399d00..00000000000 --- a/test/form/samples/custom-module-context-function/_expected/system.js +++ /dev/null @@ -1,12 +0,0 @@ -System.register([], function () { - 'use strict'; - return { - execute: function () { - - undefined.prop = 'nope'; - - lolwut.prop = '???'; - - } - }; -}); diff --git a/test/form/samples/custom-module-context-function/_expected/umd.js b/test/form/samples/custom-module-context-function/_expected/umd.js deleted file mode 100644 index 79188921edf..00000000000 --- a/test/form/samples/custom-module-context-function/_expected/umd.js +++ /dev/null @@ -1,10 +0,0 @@ -(function (factory) { - typeof define === 'function' && define.amd ? define(factory) : - factory(); -}((function () { 'use strict'; - - undefined.prop = 'nope'; - - lolwut.prop = '???'; - -}))); diff --git a/test/form/samples/custom-module-context-function/bar.js b/test/form/samples/custom-module-context-function/bar.js new file mode 100644 index 00000000000..8fac7db67d4 --- /dev/null +++ b/test/form/samples/custom-module-context-function/bar.js @@ -0,0 +1 @@ +this.prop = 'bar'; diff --git a/test/form/samples/custom-module-context-function/foo.js b/test/form/samples/custom-module-context-function/foo.js index a5a991d6d63..f1342c2914b 100644 --- a/test/form/samples/custom-module-context-function/foo.js +++ b/test/form/samples/custom-module-context-function/foo.js @@ -1 +1 @@ -this.prop = 'nope'; +this.prop = 'foo'; diff --git a/test/form/samples/custom-module-context-function/main.js b/test/form/samples/custom-module-context-function/main.js index 1323b6820ce..87b1865062b 100644 --- a/test/form/samples/custom-module-context-function/main.js +++ b/test/form/samples/custom-module-context-function/main.js @@ -1,2 +1,3 @@ import './foo.js'; -this.prop = '???'; +import './bar.js'; +this.prop = 'main'; diff --git a/test/form/samples/side-effects-internal-modules/_config.js b/test/form/samples/side-effects-internal-modules/_config.js new file mode 100644 index 00000000000..aa9d774424c --- /dev/null +++ b/test/form/samples/side-effects-internal-modules/_config.js @@ -0,0 +1,28 @@ +const assert = require('assert'); +const VIRTUAL_ID = '\0virtual'; + +module.exports = { + description: 'does not pass internal modules to moduleSideEffects', + expectedWarnings: ['EMPTY_BUNDLE'], + options: { + treeshake: { + moduleSideEffects: id => { + assert.notStrictEqual(id, VIRTUAL_ID); + return false; + } + }, + plugins: { + name: 'test-plugin', + resolveId(id) { + if (id === 'virtual') { + return VIRTUAL_ID; + } + }, + load(id) { + if (id === VIRTUAL_ID) { + return "console.log('effect')"; + } + } + } + } +}; diff --git a/test/form/samples/side-effects-internal-modules/_expected.js b/test/form/samples/side-effects-internal-modules/_expected.js new file mode 100644 index 00000000000..49686f47986 --- /dev/null +++ b/test/form/samples/side-effects-internal-modules/_expected.js @@ -0,0 +1,3 @@ +console.log('effect'); + +console.log('main'); diff --git a/test/form/samples/side-effects-internal-modules/main.js b/test/form/samples/side-effects-internal-modules/main.js new file mode 100644 index 00000000000..2a3bd7a3f51 --- /dev/null +++ b/test/form/samples/side-effects-internal-modules/main.js @@ -0,0 +1,2 @@ +import 'virtual'; +console.log('main'); diff --git a/test/function/samples/cannot-resolve-sourcemap-warning/_config.js b/test/function/samples/cannot-resolve-sourcemap-warning/_config.js new file mode 100644 index 00000000000..a803b5b72e8 --- /dev/null +++ b/test/function/samples/cannot-resolve-sourcemap-warning/_config.js @@ -0,0 +1,45 @@ +const path = require('path'); +const ID_MAIN = path.join(__dirname, 'main.js'); + +module.exports = { + description: 'handles when a sourcemap cannot be resolved in a warning', + options: { + plugins: { + name: 'test-plugin', + transform() { + return { code: 'export default this', map: { mappings: 'X' } }; + } + } + }, + warnings: [ + { + code: 'SOURCEMAP_ERROR', + id: ID_MAIN, + loc: { + column: 15, + file: ID_MAIN, + line: 1 + }, + message: + "Error when using sourcemap for reporting an error: Can't resolve original location of error.", + pos: 15 + }, + { + code: 'THIS_IS_UNDEFINED', + frame: ` + 1: export default this + ^ + `, + id: ID_MAIN, + loc: { + column: 15, + file: ID_MAIN, + line: 1 + }, + message: + "The 'this' keyword is equivalent to 'undefined' at the top level of an ES module, and has been rewritten", + pos: 15, + url: 'https://rollupjs.org/guide/en/#error-this-is-undefined' + } + ] +}; diff --git a/test/function/samples/cannot-resolve-sourcemap-warning/main.js b/test/function/samples/cannot-resolve-sourcemap-warning/main.js new file mode 100644 index 00000000000..a9244a453fb --- /dev/null +++ b/test/function/samples/cannot-resolve-sourcemap-warning/main.js @@ -0,0 +1 @@ +throw new Error('Not executed'); diff --git a/test/function/samples/emit-file/chunk-filename-not-available-buildEnd/_config.js b/test/function/samples/emit-file/chunk-filename-not-available-buildEnd/_config.js new file mode 100644 index 00000000000..95688f451a8 --- /dev/null +++ b/test/function/samples/emit-file/chunk-filename-not-available-buildEnd/_config.js @@ -0,0 +1,25 @@ +let chunkId; + +module.exports = { + description: 'Throws when accessing the filename before it has been generated in buildEnd', + options: { + input: 'main.js', + plugins: { + name: 'test-plugin', + buildStart() { + chunkId = this.emitFile({ type: 'chunk', id: 'chunk.js' }); + }, + buildEnd() { + this.getFileName(chunkId); + } + } + }, + error: { + code: 'PLUGIN_ERROR', + hook: 'buildEnd', + message: + 'Plugin error - Unable to get file name for chunk "chunk.js". Ensure that generate is called first.', + plugin: 'test-plugin', + pluginCode: 'CHUNK_NOT_GENERATED' + } +}; diff --git a/test/function/samples/emit-file/chunk-filename-not-available-buildEnd/chunk.js b/test/function/samples/emit-file/chunk-filename-not-available-buildEnd/chunk.js new file mode 100644 index 00000000000..36b1d61dd25 --- /dev/null +++ b/test/function/samples/emit-file/chunk-filename-not-available-buildEnd/chunk.js @@ -0,0 +1 @@ +console.log('chunk'); diff --git a/test/function/samples/emit-file/chunk-filename-not-available-buildEnd/main.js b/test/function/samples/emit-file/chunk-filename-not-available-buildEnd/main.js new file mode 100644 index 00000000000..c0b933d7b56 --- /dev/null +++ b/test/function/samples/emit-file/chunk-filename-not-available-buildEnd/main.js @@ -0,0 +1 @@ +console.log('main'); diff --git a/test/function/samples/emit-file/chunk-filename-not-available-renderStart/_config.js b/test/function/samples/emit-file/chunk-filename-not-available-renderStart/_config.js new file mode 100644 index 00000000000..8a35d9cfc2e --- /dev/null +++ b/test/function/samples/emit-file/chunk-filename-not-available-renderStart/_config.js @@ -0,0 +1,25 @@ +let chunkId; + +module.exports = { + description: 'Throws when accessing the filename before it has been generated in renderStart', + options: { + input: 'main.js', + plugins: { + name: 'test-plugin', + buildStart() { + chunkId = this.emitFile({ type: 'chunk', id: 'chunk.js' }); + }, + renderStart() { + this.getFileName(chunkId); + } + } + }, + generateError: { + code: 'PLUGIN_ERROR', + hook: 'renderStart', + message: + 'Plugin error - Unable to get file name for chunk "chunk.js". Ensure that generate is called first.', + plugin: 'test-plugin', + pluginCode: 'CHUNK_NOT_GENERATED' + } +}; diff --git a/test/function/samples/emit-file/chunk-filename-not-available-renderStart/chunk.js b/test/function/samples/emit-file/chunk-filename-not-available-renderStart/chunk.js new file mode 100644 index 00000000000..36b1d61dd25 --- /dev/null +++ b/test/function/samples/emit-file/chunk-filename-not-available-renderStart/chunk.js @@ -0,0 +1 @@ +console.log('chunk'); diff --git a/test/function/samples/emit-file/chunk-filename-not-available-renderStart/main.js b/test/function/samples/emit-file/chunk-filename-not-available-renderStart/main.js new file mode 100644 index 00000000000..c0b933d7b56 --- /dev/null +++ b/test/function/samples/emit-file/chunk-filename-not-available-renderStart/main.js @@ -0,0 +1 @@ +console.log('main');