diff --git a/src/Module.ts b/src/Module.ts index f3cf0f76935..83450a2e79b 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -217,7 +217,7 @@ export default class Module { private graph: Graph; private magicString!: MagicString; private namespaceVariable: NamespaceVariable = undefined as any; - private transformDependencies!: string[]; + private transformDependencies: string[] | null = null; private transitiveReexports?: string[]; constructor(graph: Graph, id: string, moduleSideEffects: boolean, isEntry: boolean) { @@ -526,13 +526,24 @@ export default class Module { originalSourcemap, resolvedIds, sourcemapChain, + transformAssets, + transformChunks, transformDependencies - }: TransformModuleJSON) { + }: TransformModuleJSON & { + transformAssets?: Asset[] | undefined; + transformChunks?: EmittedChunk[] | undefined; + }) { this.code = code; this.originalCode = originalCode; this.originalSourcemap = originalSourcemap; this.sourcemapChain = sourcemapChain as RawSourceMap[]; - this.transformDependencies = transformDependencies as string[]; + if (transformAssets) { + this.transformAssets = transformAssets; + } + if (transformChunks) { + this.transformChunks = transformChunks; + } + this.transformDependencies = transformDependencies; this.customTransformCache = customTransformCache; if (typeof moduleSideEffects === 'boolean') { this.moduleSideEffects = moduleSideEffects; diff --git a/src/ModuleLoader.ts b/src/ModuleLoader.ts index cdba19464ae..3f625d40c94 100644 --- a/src/ModuleLoader.ts +++ b/src/ModuleLoader.ts @@ -7,6 +7,7 @@ import { ExternalOption, GetManualChunk, IsExternal, + ModuleJSON, ModuleSideEffectsOption, PureModulesOption, ResolvedId, @@ -348,7 +349,7 @@ export class ModuleLoader { } return transform(this.graph, sourceDescription, module); }) - .then((source: TransformModuleJSON) => { + .then((source: TransformModuleJSON | ModuleJSON) => { module.setSource(source); this.modulesById.set(id, module); diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index 8dcb486f225..e59673c62f2 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -88,8 +88,8 @@ export interface TransformModuleJSON { export interface ModuleJSON extends TransformModuleJSON { dependencies: string[]; id: string; - transformAssets: Asset[] | void; - transformChunks: EmittedChunk[] | void; + transformAssets: Asset[] | undefined; + transformChunks: EmittedChunk[] | undefined; } export interface EmittedChunk { diff --git a/test/hooks/index.js b/test/hooks/index.js index 7f07edc6475..13de715b592 100644 --- a/test/hooks/index.js +++ b/test/hooks/index.js @@ -7,8 +7,8 @@ const rollup = require('../../dist/rollup.js'); const TEMP_DIR = path.join(__dirname, 'tmp'); describe('hooks', () => { - it('allows to read and modify options in the options hook', () => { - return rollup + it('allows to read and modify options in the options hook', () => + rollup .rollup({ input: 'input', treeshake: false, @@ -28,11 +28,10 @@ describe('hooks', () => { } ] }) - .then(bundle => {}); - }); + .then(bundle => {})); - it('allows to read and modify output options in the outputOptions hook', () => { - return rollup + it('allows to read and modify output options in the outputOptions hook', () => + rollup .rollup({ input: 'input', treeshake: false, @@ -52,19 +51,18 @@ describe('hooks', () => { } ] }) - .then(bundle => { - return bundle.generate({ + .then(bundle => + bundle.generate({ format: 'cjs', banner: 'banner' - }); - }) + }) + ) .then(({ output }) => { assert.equal(output[0].code, `new banner\n'use strict';\n\nalert('hello');\n`); - }); - }); + })); - it('allows to replace file with dir in the outputOptions hook', () => { - return rollup + it('allows to replace file with dir in the outputOptions hook', () => + rollup .rollup({ input: 'input', treeshake: false, @@ -95,8 +93,7 @@ describe('hooks', () => { const fileNames = sander.readdirSync(TEMP_DIR).sort(); assert.deepStrictEqual(fileNames, ['chunk.js', 'input.js']); return sander.rimraf(TEMP_DIR); - }); - }); + })); it('supports buildStart and buildEnd hooks', () => { let buildStartCnt = 0; @@ -206,8 +203,8 @@ describe('hooks', () => { }); }); - it('supports isExternal on plugin context', () => { - return rollup.rollup({ + it('supports isExternal on plugin context', () => + rollup.rollup({ input: 'input', external: ['test'], plugins: [ @@ -219,11 +216,10 @@ describe('hooks', () => { } } ] - }); - }); + })); - it('supports resolveId on plugin context', () => { - return rollup + it('supports resolveId on plugin context', () => + rollup .rollup({ input: 'input', plugins: [ @@ -241,13 +237,10 @@ describe('hooks', () => { } ] }) - .then(bundle => { - return bundle.generate({ format: 'es' }); - }) + .then(bundle => bundle.generate({ format: 'es' })) .then(({ output: [output] }) => { assert.equal(output.code, `alert('hello');\n`); - }); - }); + })); it('passes bundle & output object to ongenerate & onwrite hooks, with deprecation warnings', () => { let deprecationCnt = 0; @@ -284,12 +277,12 @@ describe('hooks', () => { } ] }) - .then(bundle => { - return bundle.write({ + .then(bundle => + bundle.write({ file: path.join(TEMP_DIR, 'bundle.js'), format: 'es' - }); - }) + }) + ) .then(() => { assert.equal(deprecationCnt, 2); return sander.rimraf(TEMP_DIR); @@ -348,12 +341,12 @@ describe('hooks', () => { } ] }) - .then(bundle => { - return bundle.write({ + .then(bundle => + bundle.write({ file, format: 'cjs' - }); - }) + }) + ) .then(() => { assert.deepEqual(result, [{ a: file, format: 'cjs' }, { b: file, format: 'cjs' }]); return sander.rimraf(TEMP_DIR); @@ -401,6 +394,31 @@ describe('hooks', () => { ] }); }) + .then(bundle => { + cache = bundle.cache; + return bundle.generate({ format: 'es' }); + }) + .then(({ output }) => { + assert.equal( + output[0].code, + `var input = new URL('chunk-01406d83.js', import.meta.url).href;\n\nexport default input;\n` + ); + assert.equal(output[1].fileName, 'chunk-01406d83.js'); + assert.equal(output[1].code, `console.log('chunk');\n`); + + return rollup.rollup({ + cache, + input: 'input', + plugins: [ + loader({ input: '', chunk: "console.log('chunk');" }), + { + transform() { + assert.fail('Should cache transform'); + } + } + ] + }); + }) .then(bundle => bundle.generate({ format: 'es' })) .then(({ output }) => { assert.equal( @@ -412,8 +430,8 @@ describe('hooks', () => { }); }); - it('supports asset emission', () => { - return rollup + it('supports asset emission', () => + rollup .rollup({ input: 'input', plugins: [ @@ -426,9 +444,7 @@ describe('hooks', () => { } ] }) - .then(bundle => { - return bundle.generate({ format: 'es' }); - }) + .then(bundle => bundle.generate({ format: 'es' })) .then(({ output }) => { assert.equal(output[1].isAsset, true); assert.equal(output[1].fileName, 'assets/test-19916f7d.ext'); @@ -439,8 +455,7 @@ describe('hooks', () => { output[0].code, `var input = new URL('assets/test-19916f7d.ext', import.meta.url).href;\n\nexport default input;\n` ); - }); - }); + })); it('caches asset emission in transform hook', () => { let cache; @@ -485,8 +500,33 @@ describe('hooks', () => { }); }) .then(bundle => { + cache = bundle.cache; return bundle.generate({ format: 'es' }); }) + .then(({ output }) => { + assert.equal( + output[0].code, + `var input = new URL('assets/test-19916f7d.ext', import.meta.url).href;\n\nexport default input;\n` + ); + assert.equal(output[1].fileName, 'assets/test-19916f7d.ext'); + assert.equal(output[1].source, 'hello world'); + assert.equal(output[1].fileName, 'assets/test-19916f7d.ext'); + assert.equal(output[1].source, 'hello world'); + + return rollup.rollup({ + cache, + input: 'input', + plugins: [ + loader({ input: '' }), + { + transform() { + assert.fail('Should cache transform'); + } + } + ] + }); + }) + .then(bundle => bundle.generate({ format: 'es' })) .then(({ output }) => { assert.equal( output[0].code, @@ -547,9 +587,7 @@ describe('hooks', () => { ] }); }) - .then(bundle => { - return bundle.generate({ format: 'es' }); - }) + .then(bundle => bundle.generate({ format: 'es' })) .then(({ output }) => { assert.equal(runs, 2); assert.equal(output[0].code.trim(), `alert('hello world');`); @@ -557,8 +595,8 @@ describe('hooks', () => { }); }); - it('supports CommonJS asset urls', () => { - return rollup + it('supports CommonJS asset urls', () => + rollup .rollup({ input: 'input', plugins: [ @@ -571,9 +609,7 @@ describe('hooks', () => { } ] }) - .then(bundle => { - return bundle.generate({ format: 'cjs' }); - }) + .then(bundle => bundle.generate({ format: 'cjs' })) .then(({ output: [{ code }] }) => { assert.equal( code, @@ -584,11 +620,10 @@ var input = (typeof document === 'undefined' ? new (require('u' + 'rl').URL)('fi module.exports = input; ` ); - }); - }); + })); - it('supports custom asset file names', () => { - return rollup + it('supports custom asset file names', () => + rollup .rollup({ input: 'input', plugins: [ @@ -601,17 +636,16 @@ module.exports = input; } ] }) - .then(bundle => { - return bundle.generate({ + .then(bundle => + bundle.generate({ format: 'es', assetFileNames: '[name][extname]' - }); - }) + }) + ) .then(({ output: [, output] }) => { assert.equal(output.fileName, 'test.ext'); assert.equal(output.source, 'hello world'); - }); - }); + })); it('allows setting asset source separately', () => { let assetId; @@ -631,9 +665,7 @@ module.exports = input; } ] }) - .then(bundle => { - return bundle.generate({ format: 'es' }); - }) + .then(bundle => bundle.generate({ format: 'es' })) .then(({ output: [, output] }) => { assert.equal(output.fileName, 'assets/test-19916f7d.ext'); assert.equal(output.source, 'hello world'); @@ -658,9 +690,7 @@ module.exports = input; } ] }) - .then(bundle => { - return bundle.generate({ format: 'es' }); - }) + .then(bundle => bundle.generate({ format: 'es' })) .then(({ output: [, output] }) => { assert.equal(output.source, 'hello world'); }); @@ -694,12 +724,12 @@ module.exports = input; } ] }) - .then(bundle => { - return bundle.generate({ + .then(bundle => + bundle.generate({ format: 'es', assetFileNames: '[name][extname]' - }); - }) + }) + ) .then(() => { assert.equal(deprecationCnt, 1); assert.equal(calledHook, true); @@ -729,12 +759,12 @@ module.exports = input; } ] }) - .then(bundle => { - return bundle.generate({ + .then(bundle => + bundle.generate({ format: 'es', assetFileNames: '[name][extname]' - }); - }) + }) + ) .then(() => { assert.equal(calledHook, true); }); @@ -763,19 +793,19 @@ module.exports = input; } ] }) - .then(bundle => { - return bundle.generate({ + .then(bundle => + bundle.generate({ format: 'es', assetFileNames: '[name][extname]' - }); - }) + }) + ) .then(() => { assert.equal(calledHook, true); }); }); - it('passes bundle object to generateBundle hook', () => { - return rollup + it('passes bundle object to generateBundle hook', () => + rollup .rollup({ input: 'input', plugins: [ @@ -795,13 +825,10 @@ module.exports = input; } ] }) - .then(bundle => { - return bundle.generate({ format: 'es' }); - }); - }); + .then(bundle => bundle.generate({ format: 'es' }))); - it('supports assets uniquely defined in the generateBundle hook', () => { - return rollup + it('supports assets uniquely defined in the generateBundle hook', () => + rollup .rollup({ input: 'input', plugins: [ @@ -838,11 +865,10 @@ module.exports = input; assert.equal(output2[0].code, `'use strict';\n\nalert('hello');\n`); assert.equal(output2[1].source, 'different source'); assert.equal(output2[2].source, `references assets/lateDepAsset-c107f5fc`); - }); - }); + })); - it('supports errors thrown in the generateBundle hook', () => { - return rollup + it('supports errors thrown in the generateBundle hook', () => + rollup .rollup({ input: 'input', plugins: [ @@ -854,16 +880,13 @@ module.exports = input; } ] }) - .then(bundle => { - return bundle.generate({ format: 'es' }); - }) + .then(bundle => bundle.generate({ format: 'es' })) .catch(err => { assert.equal(err.message, 'test error'); - }); - }); + })); - it('supports generateBundle hook including reporting rendered exports and source length', () => { - return rollup + it('supports generateBundle hook including reporting rendered exports and source length', () => + rollup .rollup({ input: 'input', plugins: [ @@ -889,8 +912,7 @@ module.exports = input; } ] }) - .then(bundle => bundle.generate({ format: 'es' })); - }); + .then(bundle => bundle.generate({ format: 'es' }))); it('supports writeBundle hook', () => { const file = path.join(TEMP_DIR, 'bundle.js'); @@ -925,8 +947,8 @@ module.exports = input; }); }); - it('supports this.cache for plugins', () => { - return rollup + it('supports this.cache for plugins', () => + rollup .rollup({ input: 'input', plugins: [ @@ -939,8 +961,8 @@ module.exports = input; } ] }) - .then(bundle => { - return rollup.rollup({ + .then(bundle => + rollup.rollup({ input: 'input', cache: bundle.cache, plugins: [ @@ -953,12 +975,11 @@ module.exports = input; } } ] - }); - }); - }); + }) + )); - it('throws for anonymous plugins using the cache', () => { - return rollup + it('throws for anonymous plugins using the cache', () => + rollup .rollup({ input: 'input', plugins: [ @@ -976,8 +997,7 @@ module.exports = input; .catch(err => { assert.equal(err.code, 'PLUGIN_ERROR'); assert.equal(err.pluginCode, 'ANONYMOUS_PLUGIN_CACHE'); - }); - }); + })); it('throws for two plugins using the same name and the cache', () => { // we don't throw for duplicate names unless there is cache access @@ -1023,8 +1043,8 @@ module.exports = input; }); }); - it('Allows plugins with any names using a shared cacheKey', () => { - return rollup.rollup({ + it('Allows plugins with any names using a shared cacheKey', () => + rollup.rollup({ input: 'input', plugins: [ loader({ input: `alert('hello')` }), @@ -1050,11 +1070,10 @@ module.exports = input; } } ] - }); - }); + })); - it('Evicts cache entries after cacheExpiry runs with no usage', () => { - return rollup + it('Evicts cache entries after cacheExpiry runs with no usage', () => + rollup .rollup({ input: 'input', experimentalCacheExpiry: 5, @@ -1071,9 +1090,9 @@ module.exports = input; }) .then(bundle => { let promise = Promise.resolve(); - for (let i = 0; i < 5; i++) { - promise = promise.then(() => { - return rollup.rollup({ + for (let i = 0; i < 5; i++) + promise = promise.then(() => + rollup.rollup({ cache: bundle.cache, input: 'input', experimentalCacheExpiry: 5, @@ -1086,13 +1105,12 @@ module.exports = input; } } ] - }); - }); - } + }) + ); return promise; }) - .then(bundle => { - return rollup.rollup({ + .then(bundle => + rollup.rollup({ cache: bundle.cache, input: 'input', experimentalCacheExpiry: 5, @@ -1107,12 +1125,11 @@ module.exports = input; } } ] - }); - }); - }); + }) + )); - it('Supports disabling the cache with cache: false', () => { - return rollup + it('Supports disabling the cache with cache: false', () => + rollup .rollup({ input: 'input', cache: false, @@ -1130,11 +1147,10 @@ module.exports = input; }) .then(bundle => { assert.equal(bundle.cache, undefined); - }); - }); + })); - it('Disables the default transform cache when using cache in transform only', () => { - return rollup + it('Disables the default transform cache when using cache in transform only', () => + rollup .rollup({ input: 'input', plugins: [ @@ -1148,8 +1164,8 @@ module.exports = input; } ] }) - .then(bundle => { - return rollup.rollup({ + .then(bundle => + rollup.rollup({ input: 'input', cache: bundle.cache, plugins: [ @@ -1162,17 +1178,16 @@ module.exports = input; } } ] - }); - }) - .then(bundle => { - return bundle.generate({ + }) + ) + .then(bundle => + bundle.generate({ format: 'es' - }); - }) + }) + ) .then(({ output }) => { assert.equal(output[0].code.trim(), `alert('hello');`); - }); - }); + })); it('supports renderStart hook', () => { let renderStartCount = 0;