diff --git a/packages/angular_devkit/build_optimizer/src/build-optimizer/build-optimizer.ts b/packages/angular_devkit/build_optimizer/src/build-optimizer/build-optimizer.ts index b339fd9793..d737a27a56 100644 --- a/packages/angular_devkit/build_optimizer/src/build-optimizer/build-optimizer.ts +++ b/packages/angular_devkit/build_optimizer/src/build-optimizer/build-optimizer.ts @@ -16,7 +16,22 @@ import { getScrubFileTransformer } from '../transforms/scrub-file'; const hasDecorators = /decorators/; const hasCtorParameters = /ctorParameters/; const hasTsHelpers = /var (__extends|__decorate|__metadata|__param) = /; -const isAngularPackage = /(\\|\/)node_modules(\\|\/)@angular(\\|\/)/; +const isAngularModuleFile = /\.es5\.js$/; +const whitelistedAngularModules = [ + /(\\|\/)node_modules(\\|\/)@angular(\\|\/)animations(\\|\/)/, + /(\\|\/)node_modules(\\|\/)@angular(\\|\/)common(\\|\/)/, + /(\\|\/)node_modules(\\|\/)@angular(\\|\/)compiler(\\|\/)/, + /(\\|\/)node_modules(\\|\/)@angular(\\|\/)core(\\|\/)/, + /(\\|\/)node_modules(\\|\/)@angular(\\|\/)forms(\\|\/)/, + /(\\|\/)node_modules(\\|\/)@angular(\\|\/)http(\\|\/)/, + /(\\|\/)node_modules(\\|\/)@angular(\\|\/)platform-browser-dynamic(\\|\/)/, + /(\\|\/)node_modules(\\|\/)@angular(\\|\/)platform-browser(\\|\/)/, + /(\\|\/)node_modules(\\|\/)@angular(\\|\/)platform-webworker-dynamic(\\|\/)/, + /(\\|\/)node_modules(\\|\/)@angular(\\|\/)platform-webworker(\\|\/)/, + /(\\|\/)node_modules(\\|\/)@angular(\\|\/)router(\\|\/)/, + /(\\|\/)node_modules(\\|\/)@angular(\\|\/)upgrade(\\|\/)/, + /(\\|\/)node_modules(\\|\/)@angular(\\|\/)material(\\|\/)/, +]; export interface BuildOptimizerOptions { content?: string; @@ -46,13 +61,15 @@ export function buildOptimizer(options: BuildOptimizerOptions): TransformJavascr getTransforms.push(getImportTslibTransformer); } - if (inputFilePath && isAngularPackage.test(inputFilePath)) { - // Order matters, getPrefixFunctionsTransformer needs to be called before - // getFoldFileTransformer. + if (inputFilePath + && isAngularModuleFile.test(inputFilePath) + && whitelistedAngularModules.some((re) => re.test(inputFilePath)) + ) { getTransforms.push( - // getPrefixFunctionsTransformer is rather dangerous. + // getPrefixFunctionsTransformer is rather dangerous, apply only to known pure modules. // It will mark both `require()` calls and `console.log(stuff)` as pure. - // We only apply it to @angular/* packages, since we know they are safe. + // We only apply it to whitelisted modules, since we know they are safe. + // getPrefixFunctionsTransformer needs to be before getFoldFileTransformer. getPrefixFunctionsTransformer, getScrubFileTransformer, getFoldFileTransformer, diff --git a/packages/angular_devkit/build_optimizer/src/build-optimizer/build-optimizer_spec.ts b/packages/angular_devkit/build_optimizer/src/build-optimizer/build-optimizer_spec.ts index d8bb7a64fe..64b9c0cc7c 100644 --- a/packages/angular_devkit/build_optimizer/src/build-optimizer/build-optimizer_spec.ts +++ b/packages/angular_devkit/build_optimizer/src/build-optimizer/build-optimizer_spec.ts @@ -40,7 +40,7 @@ describe('build-optimizer', () => { `; // tslint:enable:max-line-length - const inputFilePath = '/node_modules/@angular/some-lib'; + const inputFilePath = '/node_modules/@angular/core/@angular/core.es5.js'; const boOutput = buildOptimizer({ content: input, inputFilePath }); expect(oneLine`${boOutput.content}`).toEqual(output); expect(boOutput.emitSkipped).toEqual(false); @@ -83,6 +83,31 @@ describe('build-optimizer', () => { }); }); + describe('whitelisted modules', () => { + // This statement is considered pure by getPrefixFunctionsTransformer on whitelisted modules. + const input = 'console.log(42);'; + const output = '/*@__PURE__*/ console.log(42);'; + + it('should process whitelisted modules', () => { + const inputFilePath = '/node_modules/@angular/core/@angular/core.es5.js'; + const boOutput = buildOptimizer({ content: input, inputFilePath }); + expect(boOutput.content).toContain(output); + expect(boOutput.emitSkipped).toEqual(false); + }); + + it('should not process non-whitelisted modules', () => { + const inputFilePath = '/node_modules/other-package/core.es5.js'; + const boOutput = buildOptimizer({ content: input, inputFilePath }); + expect(boOutput.emitSkipped).toEqual(true); + }); + + it('should not process non-whitelisted umd modules', () => { + const inputFilePath = '/node_modules/@angular/core/bundles/core.umd.js'; + const boOutput = buildOptimizer({ content: input, inputFilePath }); + expect(boOutput.emitSkipped).toEqual(true); + }); + }); + describe('sourcemaps', () => { const transformableInput = oneLine` ${imports}