From edfeedd8b68f8af56d8e8a29d303c87d24152356 Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Sun, 9 Jan 2022 06:47:17 +0100 Subject: [PATCH] Implement shouldTransformCachedModule --- src/ModuleLoader.ts | 12 +++++++++- src/rollup/types.d.ts | 19 +++++++++++++-- src/utils/PluginDriver.ts | 1 + test/incremental/index.js | 50 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 3 deletions(-) diff --git a/src/ModuleLoader.ts b/src/ModuleLoader.ts index ede3546b14f..648d9aba78b 100644 --- a/src/ModuleLoader.ts +++ b/src/ModuleLoader.ts @@ -274,7 +274,17 @@ export class ModuleLoader { if ( cachedModule && !cachedModule.customTransformCache && - cachedModule.originalCode === sourceDescription.code + cachedModule.originalCode === sourceDescription.code && + !(await this.pluginDriver.hookFirst('shouldTransformCachedModule', [ + { + ast: cachedModule.ast, + code: cachedModule.code, + id: cachedModule.id, + meta: cachedModule.meta, + moduleSideEffects: cachedModule.moduleSideEffects, + syntheticNamedExports: cachedModule.syntheticNamedExports + } + ])) ) { if (cachedModule.transformFiles) { for (const emittedFile of cachedModule.transformFiles) diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index 1197dc41e8a..55c3c0b1f87 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -113,7 +113,7 @@ export interface TransformModuleJSON extends Partial> transformDependencies: string[]; } -export interface ModuleJSON extends TransformModuleJSON { +export interface ModuleJSON extends ModuleOptions, TransformModuleJSON { ast: AcornNode; dependencies: string[]; id: string; @@ -242,6 +242,18 @@ export type ResolveIdHook = ( options: { custom?: CustomPluginOptions; isEntry: boolean } ) => Promise | ResolveIdResult; +export type ShouldTransformCachedModuleHook = ( + this: PluginContext, + options: { + ast: AcornNode; + code: string; + id: string; + meta: CustomPluginOptions; + moduleSideEffects: boolean | 'no-treeshake'; + syntheticNamedExports: boolean | string; + } +) => Promise | boolean; + export type IsExternal = ( source: string, importer: string | undefined, @@ -367,6 +379,7 @@ export interface PluginHooks extends OutputPluginHooks { ) => Promise | InputOptions | null | undefined; resolveDynamicImport: ResolveDynamicImportHook; resolveId: ResolveIdHook; + shouldTransformCachedModule: ShouldTransformCachedModuleHook; transform: TransformHook; watchChange: WatchChangeHook; } @@ -419,6 +432,7 @@ export type AsyncPluginHooks = | 'renderStart' | 'resolveDynamicImport' | 'resolveId' + | 'shouldTransformCachedModule' | 'transform' | 'writeBundle' | 'closeBundle'; @@ -434,7 +448,8 @@ export type FirstPluginHooks = | 'resolveDynamicImport' | 'resolveFileUrl' | 'resolveId' - | 'resolveImportMeta'; + | 'resolveImportMeta' + | 'shouldTransformCachedModule'; export type SequentialPluginHooks = | 'augmentChunkHash' diff --git a/src/utils/PluginDriver.ts b/src/utils/PluginDriver.ts index 1a77fe57851..b96b54880b1 100644 --- a/src/utils/PluginDriver.ts +++ b/src/utils/PluginDriver.ts @@ -55,6 +55,7 @@ const inputHookNames: { options: 1, resolveDynamicImport: 1, resolveId: 1, + shouldTransformCachedModule: 1, transform: 1, watchChange: 1 }; diff --git a/test/incremental/index.js b/test/incremental/index.js index 1595ca248d7..794fcc6a17f 100644 --- a/test/incremental/index.js +++ b/test/incremental/index.js @@ -336,4 +336,54 @@ describe('incremental', () => { assert.strictEqual(transformCalls, 2); assert.strictEqual(moduleParsedCalls, 4); // should not be cached }); + + it('runs shouldTransformCachedModule when using a cached module', async () => { + let shouldTransformCachedModuleCalls = 0; + + const transformPlugin = { + async shouldTransformCachedModule({ ast, id, meta, ...other }) { + shouldTransformCachedModuleCalls++; + assert.strictEqual(ast.type, 'Program'); + assert.deepStrictEqual(other, { + code: modules[id], + moduleSideEffects: true, + syntheticNamedExports: false + }); + switch (id) { + case 'foo': + assert.deepStrictEqual(meta, { transform: { calls: 1, id } }); + // we return promises to ensure they are awaited + return Promise.resolve(false); + case 'entry': + assert.deepStrictEqual(meta, { transform: { calls: 0, id } }); + return Promise.resolve(true); + default: + throw new Error(`Unexpected id ${id}.`); + } + }, + transform: (code, id) => { + return { meta: { transform: { calls: transformCalls, id } } }; + } + }; + const cache = await rollup.rollup({ + input: 'entry', + plugins: [transformPlugin, plugin] + }); + assert.strictEqual(shouldTransformCachedModuleCalls, 0); + assert.strictEqual(transformCalls, 2); + + const { + cache: { modules: cachedModules } + } = await rollup.rollup({ + input: 'entry', + plugins: [transformPlugin, plugin], + cache + }); + assert.strictEqual(shouldTransformCachedModuleCalls, 2); + assert.strictEqual(transformCalls, 3); + assert.strictEqual(cachedModules[0].id, 'foo'); + assert.deepStrictEqual(cachedModules[0].meta, { transform: { calls: 1, id: 'foo' } }); + assert.strictEqual(cachedModules[1].id, 'entry'); + assert.deepStrictEqual(cachedModules[1].meta, { transform: { calls: 2, id: 'entry' } }); + }); });