From 013c3337e0ca9cab5ee5ab6c9556f874572034bd Mon Sep 17 00:00:00 2001 From: JoostK Date: Sun, 11 Nov 2018 19:16:04 +0100 Subject: [PATCH 1/4] =?UTF-8?q?fix(ivy):=20prevent=20ngcc=20from=20referen?= =?UTF-8?q?cing=20missing=20=C9=B5setClassMetadata?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When ngtsc compiles @angular/core, it rewrites core imports to the r3_symbols.ts file that exposes all internal symbols under their external name. When creating the FESM bundle, the r3_symbols.ts file causes the external symbol names to be rewritten to their internal name. Under ngcc compilations of FESM bundles, the indirection of r3_symbols.ts is no longer in place such that the external names are retained in the bundle. Previously, the external name `ɵdefineNgModule` was explicitly declared internally to resolve this issue, but the recently added `setClassMetadata` was not declared as such, causing runtime errors. Instead of relying on the r3_symbols.ts file to perform the rewrite of the external modules to their internal variants, the translation is moved into the `ImportManager` during the compilation itself. This avoids the need for providing the external name manually. --- integration/ngcc/test.sh | 8 +- .../ngcc/src/rendering/ngcc_import_manager.ts | 7 +- .../src/ngcc/test/rendering/renderer_spec.ts | 79 +++++++++++++++---- .../src/ngtsc/translator/src/translator.ts | 56 ++++++++----- .../compiler-cli/src/ngtsc/util/src/path.ts | 6 +- .../core/src/core_render3_private_export.ts | 5 +- packages/core/src/r3_symbols.ts | 13 +-- .../hello_world_r2/bundle.golden_symbols.json | 3 - .../todo_r2/bundle.golden_symbols.json | 3 - 9 files changed, 120 insertions(+), 60 deletions(-) diff --git a/integration/ngcc/test.sh b/integration/ngcc/test.sh index c88adbb4aca6..d46ad3201d3e 100755 --- a/integration/ngcc/test.sh +++ b/integration/ngcc/test.sh @@ -24,13 +24,13 @@ ivy-ngcc if [[ $? != 0 ]]; then exit 1; fi # Did it compile @angular/core/ApplicationModule correctly? - grep "ApplicationModule.ngModuleDef = ɵdefineNgModule" node_modules/@angular/core/fesm2015/core.js + grep "ApplicationModule.ngModuleDef = defineNgModule" node_modules/@angular/core/fesm2015/core.js if [[ $? != 0 ]]; then exit 1; fi - grep "ApplicationModule.ngModuleDef = ɵdefineNgModule" node_modules/@angular/core/fesm5/core.js + grep "ApplicationModule.ngModuleDef = defineNgModule" node_modules/@angular/core/fesm5/core.js if [[ $? != 0 ]]; then exit 1; fi - grep "ApplicationModule.ngModuleDef = ɵngcc0.ɵdefineNgModule" node_modules/@angular/core/esm2015/src/application_module.js + grep "ApplicationModule.ngModuleDef = ɵngcc0.defineNgModule" node_modules/@angular/core/esm2015/src/application_module.js if [[ $? != 0 ]]; then exit 1; fi - grep "ApplicationModule.ngModuleDef = ɵngcc0.ɵdefineNgModule" node_modules/@angular/core/esm5/src/application_module.js + grep "ApplicationModule.ngModuleDef = ɵngcc0.defineNgModule" node_modules/@angular/core/esm5/src/application_module.js if [[ $? != 0 ]]; then exit 1; fi # Can it be safely run again (as a noop)? diff --git a/packages/compiler-cli/src/ngcc/src/rendering/ngcc_import_manager.ts b/packages/compiler-cli/src/ngcc/src/rendering/ngcc_import_manager.ts index e8d3aa05a031..2dbd05f1d846 100644 --- a/packages/compiler-cli/src/ngcc/src/rendering/ngcc_import_manager.ts +++ b/packages/compiler-cli/src/ngcc/src/rendering/ngcc_import_manager.ts @@ -12,10 +12,11 @@ import {ImportManager} from '../../../ngtsc/translator'; export class NgccImportManager extends ImportManager { constructor(private isFlat: boolean, isCore: boolean, prefix?: string) { super(isCore, prefix); } - generateNamedImport(moduleName: string, symbol: string): string|null { + generateNamedImport(moduleName: string, symbol: string): + {moduleImport: string | null, symbol: string} { if (this.isFlat && this.isCore && moduleName === '@angular/core') { - return null; + return {moduleImport: null, symbol: this.rewriteSymbol(moduleName, symbol)}; } return super.generateNamedImport(moduleName, symbol); } -} \ No newline at end of file +} diff --git a/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts b/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts index 3b30a0160052..1fc8c6da8e1c 100644 --- a/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts +++ b/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts @@ -17,7 +17,10 @@ import {Esm2015ReflectionHost} from '../../src/host/esm2015_host'; import {Renderer} from '../../src/rendering/renderer'; class TestRenderer extends Renderer { - constructor(host: Esm2015ReflectionHost) { super(host, false, null, '/src', '/dist', false); } + constructor( + host: Esm2015ReflectionHost, isCore: boolean, rewriteCoreImportsTo: ts.SourceFile|null) { + super(host, isCore, rewriteCoreImportsTo, '/src', '/dist', false); + } addImports(output: MagicString, imports: {name: string, as: string}[]) { output.prepend('\n// ADD IMPORTS\n'); } @@ -35,13 +38,18 @@ class TestRenderer extends Renderer { } } -function createTestRenderer(file: {name: string, contents: string}) { - const program = makeProgram(file); - const host = new Esm2015ReflectionHost(false, program.getTypeChecker()); +function createTestRenderer( + files: {name: string, contents: string}[], + options: {isCore?: boolean, rewriteCoreImportsTo?: string} = {}) { + const program = makeProgram(...files); + const host = new Esm2015ReflectionHost(options.isCore || false, program.getTypeChecker()); const decorationAnalyses = - new DecorationAnalyzer(program.getTypeChecker(), host, [''], false).analyzeProgram(program); + new DecorationAnalyzer(program.getTypeChecker(), host, [''], options.isCore || false) + .analyzeProgram(program); const switchMarkerAnalyses = new SwitchMarkerAnalyzer(host).analyzeProgram(program); - const renderer = new TestRenderer(host); + const rewriteCoreImportsTo = + options.rewriteCoreImportsTo ? program.getSourceFile(options.rewriteCoreImportsTo) ! : null; + const renderer = new TestRenderer(host, options.isCore || false, rewriteCoreImportsTo); spyOn(renderer, 'addImports').and.callThrough(); spyOn(renderer, 'addDefinitions').and.callThrough(); spyOn(renderer, 'removeDecorators').and.callThrough(); @@ -94,7 +102,7 @@ describe('Renderer', () => { it('should render the modified contents; and a new map file, if the original provided no map file.', () => { const {renderer, program, decorationAnalyses, switchMarkerAnalyses} = - createTestRenderer(INPUT_PROGRAM); + createTestRenderer([INPUT_PROGRAM]); const result = renderer.renderProgram(program, decorationAnalyses, switchMarkerAnalyses); expect(result[0].path).toEqual('/dist/file.js'); expect(result[0].contents) @@ -106,7 +114,7 @@ describe('Renderer', () => { it('should call addImports with the source code and info about the core Angular library.', () => { const {decorationAnalyses, program, renderer, switchMarkerAnalyses} = - createTestRenderer(INPUT_PROGRAM); + createTestRenderer([INPUT_PROGRAM]); renderer.renderProgram(program, decorationAnalyses, switchMarkerAnalyses); const addImportsSpy = renderer.addImports as jasmine.Spy; expect(addImportsSpy.calls.first().args[0].toString()).toEqual(RENDERED_CONTENTS); @@ -118,7 +126,7 @@ describe('Renderer', () => { it('should call addDefinitions with the source code, the analyzed class and the renderered definitions.', () => { const {decorationAnalyses, program, renderer, switchMarkerAnalyses} = - createTestRenderer(INPUT_PROGRAM); + createTestRenderer([INPUT_PROGRAM]); renderer.renderProgram(program, decorationAnalyses, switchMarkerAnalyses); const addDefinitionsSpy = renderer.addDefinitions as jasmine.Spy; expect(addDefinitionsSpy.calls.first().args[0].toString()).toEqual(RENDERED_CONTENTS); @@ -137,7 +145,7 @@ A.ngDirectiveDef = ɵngcc0.ɵdefineDirective({ type: A, selectors: [["", "a", "" it('should call removeDecorators with the source code, a map of class decorators that have been analyzed', () => { const {decorationAnalyses, program, renderer, switchMarkerAnalyses} = - createTestRenderer(INPUT_PROGRAM); + createTestRenderer([INPUT_PROGRAM]); renderer.renderProgram(program, decorationAnalyses, switchMarkerAnalyses); const removeDecoratorsSpy = renderer.removeDecorators as jasmine.Spy; expect(removeDecoratorsSpy.calls.first().args[0].toString()).toEqual(RENDERED_CONTENTS); @@ -157,10 +165,10 @@ A.ngDirectiveDef = ɵngcc0.ɵdefineDirective({ type: A, selectors: [["", "a", "" it('should merge any inline source map from the original file and write the output as an inline source map', () => { - const {decorationAnalyses, program, renderer, switchMarkerAnalyses} = createTestRenderer({ + const {decorationAnalyses, program, renderer, switchMarkerAnalyses} = createTestRenderer([{ ...INPUT_PROGRAM, contents: INPUT_PROGRAM.contents + '\n' + INPUT_PROGRAM_MAP.toComment() - }); + }]); const result = renderer.renderProgram(program, decorationAnalyses, switchMarkerAnalyses); expect(result[0].path).toEqual('/dist/file.js'); expect(result[0].contents) @@ -172,10 +180,10 @@ A.ngDirectiveDef = ɵngcc0.ɵdefineDirective({ type: A, selectors: [["", "a", "" () => { // Mock out reading the map file from disk spyOn(fs, 'readFileSync').and.returnValue(INPUT_PROGRAM_MAP.toJSON()); - const {decorationAnalyses, program, renderer, switchMarkerAnalyses} = createTestRenderer({ + const {decorationAnalyses, program, renderer, switchMarkerAnalyses} = createTestRenderer([{ ...INPUT_PROGRAM, contents: INPUT_PROGRAM.contents + '\n//# sourceMappingURL=file.js.map' - }); + }]); const result = renderer.renderProgram(program, decorationAnalyses, switchMarkerAnalyses); expect(result[0].path).toEqual('/dist/file.js'); expect(result[0].contents) @@ -183,5 +191,48 @@ A.ngDirectiveDef = ɵngcc0.ɵdefineDirective({ type: A, selectors: [["", "a", "" expect(result[1].path).toEqual('/dist/file.js.map'); expect(result[1].contents).toEqual(MERGED_OUTPUT_PROGRAM_MAP.toJSON()); }); + + describe('@angular/core support', () => { + + it('should render relative imports in ESM bundles', () => { + const R3_SYMBOLS_FILE = { + name: '/src/r3_symbols.js', + contents: `export const NgModule = () => null;` + }; + const CORE_FILE = { + name: '/src/core.js', + contents: + `import { NgModule } from './ng_module';\nexport class MyModule {}\nMyModule.decorators = [\n { type: NgModule, args: [] }\n];\n` + }; + + const {decorationAnalyses, program, renderer, switchMarkerAnalyses} = createTestRenderer( + [R3_SYMBOLS_FILE, CORE_FILE], + {isCore: true, rewriteCoreImportsTo: R3_SYMBOLS_FILE.name}); + renderer.renderProgram(program, decorationAnalyses, switchMarkerAnalyses); + const addDefinitionsSpy = renderer.addDefinitions as jasmine.Spy; + expect(addDefinitionsSpy.calls.first().args[2]) + .toContain(`/*@__PURE__*/ ɵngcc0.setClassMetadata(`); + const addImportsSpy = renderer.addImports as jasmine.Spy; + expect(addImportsSpy.calls.first().args[1]).toEqual([{name: './r3_symbols', as: 'ɵngcc0'}]); + }); + + it('should render no imports in FESM bundles', () => { + const CORE_FILE = { + name: '/src/core.js', + contents: `export const NgModule = () => null; + export class MyModule {}\nMyModule.decorators = [\n { type: NgModule, args: [] }\n];\n` + }; + + const {decorationAnalyses, program, renderer, switchMarkerAnalyses} = + createTestRenderer([CORE_FILE], {isCore: true}); + renderer.renderProgram(program, decorationAnalyses, switchMarkerAnalyses); + const addDefinitionsSpy = renderer.addDefinitions as jasmine.Spy; + expect(addDefinitionsSpy.calls.first().args[2]) + .toContain(`/*@__PURE__*/ setClassMetadata(`); + const addImportsSpy = renderer.addImports as jasmine.Spy; + expect(addImportsSpy.calls.first().args[1]).toEqual([]); + }); + + }); }); }); diff --git a/packages/compiler-cli/src/ngtsc/translator/src/translator.ts b/packages/compiler-cli/src/ngtsc/translator/src/translator.ts index cb9eddd0eee5..e24d0d69f4cd 100644 --- a/packages/compiler-cli/src/ngtsc/translator/src/translator.ts +++ b/packages/compiler-cli/src/ngtsc/translator/src/translator.ts @@ -38,16 +38,16 @@ const BINARY_OPERATORS = new Map([ [BinaryOperator.Plus, ts.SyntaxKind.PlusToken], ]); -const CORE_SUPPORTED_SYMBOLS = new Set([ - 'defineInjectable', - 'defineInjector', - 'ɵdefineNgModule', - 'inject', - 'ɵsetClassMetadata', - 'ɵInjectableDef', - 'ɵInjectorDef', - 'ɵNgModuleDefWithMeta', - 'ɵNgModuleFactory', +const CORE_SUPPORTED_SYMBOLS = new Map([ + ['defineInjectable', 'defineInjectable'], + ['defineInjector', 'defineInjector'], + ['ɵdefineNgModule', 'defineNgModule'], + ['inject', 'inject'], + ['ɵsetClassMetadata', 'setClassMetadata'], + ['ɵInjectableDef', 'InjectableDef'], + ['ɵInjectorDef', 'InjectorDef'], + ['ɵNgModuleDefWithMeta', 'NgModuleDefWithMeta'], + ['ɵNgModuleFactory', 'NgModuleFactory'], ]); export class ImportManager { @@ -56,14 +56,28 @@ export class ImportManager { constructor(protected isCore: boolean, private prefix = 'i') {} - generateNamedImport(moduleName: string, symbol: string): string|null { + generateNamedImport(moduleName: string, symbol: string): + {moduleImport: string | null, symbol: string} { if (!this.moduleToIndex.has(moduleName)) { this.moduleToIndex.set(moduleName, `${this.prefix}${this.nextIndex++}`); } - if (this.isCore && moduleName === '@angular/core' && !CORE_SUPPORTED_SYMBOLS.has(symbol)) { - throw new Error(`Importing unexpected symbol ${symbol} while compiling core`); + + return { + moduleImport: this.moduleToIndex.get(moduleName) !, + symbol: this.rewriteSymbol(moduleName, symbol) + }; + } + + protected rewriteSymbol(moduleName: string, symbol: string): string { + if (this.isCore && moduleName === '@angular/core') { + if (!CORE_SUPPORTED_SYMBOLS.has(symbol)) { + throw new Error(`Importing unexpected symbol ${symbol} while compiling core`); + } + + symbol = CORE_SUPPORTED_SYMBOLS.get(symbol) !; } - return this.moduleToIndex.get(moduleName) !; + + return symbol; } getAllImports(contextPath: string, rewriteCoreImportsTo: ts.SourceFile|null): @@ -216,12 +230,13 @@ class ExpressionTranslatorVisitor implements ExpressionVisitor, StatementVisitor if (ast.value.moduleName === null || ast.value.name === null) { throw new Error(`Import unknown module or symbol ${ast.value}`); } - const importIdentifier = this.imports.generateNamedImport(ast.value.moduleName, ast.value.name); - if (importIdentifier === null) { - return ts.createIdentifier(ast.value.name); + const {moduleImport, symbol} = + this.imports.generateNamedImport(ast.value.moduleName, ast.value.name); + if (moduleImport === null) { + return ts.createIdentifier(symbol); } else { return ts.createPropertyAccess( - ts.createIdentifier(importIdentifier), ts.createIdentifier(ast.value.name)); + ts.createIdentifier(moduleImport), ts.createIdentifier(symbol)); } } @@ -382,8 +397,9 @@ export class TypeTranslatorVisitor implements ExpressionVisitor, TypeVisitor { if (ast.value.moduleName === null || ast.value.name === null) { throw new Error(`Import unknown module or symbol`); } - const moduleSymbol = this.imports.generateNamedImport(ast.value.moduleName, ast.value.name); - const base = `${moduleSymbol}.${ast.value.name}`; + const {moduleImport, symbol} = + this.imports.generateNamedImport(ast.value.moduleName, ast.value.name); + const base = moduleImport ? `${moduleImport}.${symbol}` : symbol; if (ast.typeParams !== null) { const generics = ast.typeParams.map(type => type.visitType(this, context)).join(', '); return `${base}<${generics}>`; diff --git a/packages/compiler-cli/src/ngtsc/util/src/path.ts b/packages/compiler-cli/src/ngtsc/util/src/path.ts index 954eba677729..6740d7d8a0b5 100644 --- a/packages/compiler-cli/src/ngtsc/util/src/path.ts +++ b/packages/compiler-cli/src/ngtsc/util/src/path.ts @@ -10,10 +10,10 @@ import * as path from 'path'; -const TS_DTS_EXTENSION = /(\.d)?\.ts$/; +const TS_DTS_JS_EXTENSION = /(\.d)?\.ts|\.js$/; export function relativePathBetween(from: string, to: string): string|null { - let relative = path.posix.relative(path.dirname(from), to).replace(TS_DTS_EXTENSION, ''); + let relative = path.posix.relative(path.dirname(from), to).replace(TS_DTS_JS_EXTENSION, ''); if (relative === '') { return null; @@ -25,4 +25,4 @@ export function relativePathBetween(from: string, to: string): string|null { } return relative; -} \ No newline at end of file +} diff --git a/packages/core/src/core_render3_private_export.ts b/packages/core/src/core_render3_private_export.ts index 228e36c58cc6..0c750ebd9e79 100644 --- a/packages/core/src/core_render3_private_export.ts +++ b/packages/core/src/core_render3_private_export.ts @@ -7,15 +7,12 @@ */ // clang-format off -// We need to have `ɵdefineNgModule` defined locally for flat-file ngcc compilation. -// More details in the commit where this is added. -import {defineNgModule} from './render3/index'; -export const ɵdefineNgModule = defineNgModule; export { defineBase as ɵdefineBase, defineComponent as ɵdefineComponent, defineDirective as ɵdefineDirective, definePipe as ɵdefinePipe, + defineNgModule as ɵdefineNgModule, detectChanges as ɵdetectChanges, renderComponent as ɵrenderComponent, ComponentType as ɵComponentType, diff --git a/packages/core/src/r3_symbols.ts b/packages/core/src/r3_symbols.ts index b5c702c38959..2bddd57e0230 100644 --- a/packages/core/src/r3_symbols.ts +++ b/packages/core/src/r3_symbols.ts @@ -14,17 +14,18 @@ * compiler writes imports to this file. * * Only a subset of such imports are supported - core is not allowed to declare components or pipes. - * A check in ngtsc's translator.ts validates this condition. + * A check in ngtsc's translator.ts validates this condition. The translator is responsible for + * translating an external name (prefixed with ɵ) to the internal symbol name as exported below. * * The below symbols are used for @Injectable and @NgModule compilation. */ -export {InjectableDef as ɵInjectableDef, InjectorDef as ɵInjectorDef, defineInjectable, defineInjector} from './di/defs'; +export {InjectableDef, InjectorDef, defineInjectable, defineInjector} from './di/defs'; export {inject} from './di/injector_compatibility'; -export {NgModuleDef as ɵNgModuleDef, NgModuleDefWithMeta as ɵNgModuleDefWithMeta} from './metadata/ng_module'; -export {defineNgModule as ɵdefineNgModule} from './render3/definition'; -export {setClassMetadata as ɵsetClassMetadata} from './render3/metadata'; -export {NgModuleFactory as ɵNgModuleFactory} from './render3/ng_module_ref'; +export {NgModuleDef, NgModuleDefWithMeta} from './metadata/ng_module'; +export {defineNgModule} from './render3/definition'; +export {setClassMetadata} from './render3/metadata'; +export {NgModuleFactory} from './render3/ng_module_ref'; /** diff --git a/packages/core/test/bundling/hello_world_r2/bundle.golden_symbols.json b/packages/core/test/bundling/hello_world_r2/bundle.golden_symbols.json index f66d9efc0d00..1c1f14582906 100644 --- a/packages/core/test/bundling/hello_world_r2/bundle.golden_symbols.json +++ b/packages/core/test/bundling/hello_world_r2/bundle.golden_symbols.json @@ -1417,8 +1417,5 @@ }, { "name": "wtfLeave" - }, - { - "name": "ɵdefineNgModule" } ] \ No newline at end of file diff --git a/packages/core/test/bundling/todo_r2/bundle.golden_symbols.json b/packages/core/test/bundling/todo_r2/bundle.golden_symbols.json index d5a236d5fb9c..82a34c07d52e 100644 --- a/packages/core/test/bundling/todo_r2/bundle.golden_symbols.json +++ b/packages/core/test/bundling/todo_r2/bundle.golden_symbols.json @@ -2689,8 +2689,5 @@ }, { "name": "wtfLeave" - }, - { - "name": "ɵdefineNgModule" } ] \ No newline at end of file From dcbead9b0b7dab339748e752010f788741019f11 Mon Sep 17 00:00:00 2001 From: JoostK Date: Mon, 12 Nov 2018 00:07:42 +0100 Subject: [PATCH 2/4] fix(ivy): let ngcc transform @angular/core typings with relative imports --- .../src/ngcc/src/packages/transformer.ts | 40 ++++++++++++------- .../src/ngcc/src/rendering/esm5_renderer.ts | 7 +++- .../src/ngcc/src/rendering/esm_renderer.ts | 7 +++- .../src/ngcc/src/rendering/renderer.ts | 5 ++- .../test/rendering/esm2015_renderer_spec.ts | 2 +- .../ngcc/test/rendering/esm5_renderer_spec.ts | 2 +- .../src/ngcc/test/rendering/renderer_spec.ts | 2 +- 7 files changed, 42 insertions(+), 23 deletions(-) diff --git a/packages/compiler-cli/src/ngcc/src/packages/transformer.ts b/packages/compiler-cli/src/ngcc/src/packages/transformer.ts index 53d2a18def5e..0a8ccdcc28ad 100644 --- a/packages/compiler-cli/src/ngcc/src/packages/transformer.ts +++ b/packages/compiler-cli/src/ngcc/src/packages/transformer.ts @@ -70,27 +70,36 @@ export class Transformer { const host = ts.createCompilerHost(options); const rootDirs = this.getRootDirs(host, options); const isCore = entryPoint.name === '@angular/core'; - const r3SymbolsPath = isCore ? this.findR3SymbolsPath(dirname(entryPointFilePath)) : null; + const r3SymbolsPath = + isCore ? this.findR3SymbolsPath(dirname(entryPointFilePath), 'r3_symbols.js') : null; const rootPaths = r3SymbolsPath ? [entryPointFilePath, r3SymbolsPath] : [entryPointFilePath]; const packageProgram = ts.createProgram(rootPaths, options, host); - console.time(entryPoint.name + '(dtsmappper creation)'); + const r3SymbolsFile = r3SymbolsPath && packageProgram.getSourceFile(r3SymbolsPath) || null; + + console.time(`${entryPoint.name} (dtsMapper creation)`); const dtsFilePath = entryPoint.typings; - const dtsProgram = transformDts ? ts.createProgram([entryPoint.typings], options, host) : null; - console.timeEnd(entryPoint.name + '(dtsmappper creation)'); + const r3SymbolsDtsPath = + isCore ? this.findR3SymbolsPath(dirname(dtsFilePath), 'r3_symbols.d.ts') : null; + const rootDtsPaths = r3SymbolsDtsPath ? [dtsFilePath, r3SymbolsDtsPath] : [dtsFilePath]; + const dtsProgram = transformDts ? ts.createProgram(rootDtsPaths, options, host) : null; + const r3SymbolsDtsFile = + dtsProgram && r3SymbolsDtsPath && dtsProgram.getSourceFile(r3SymbolsDtsPath) || null; + console.timeEnd(`${entryPoint.name} (dtsMapper creation)`); + const reflectionHost = this.getHost(isCore, format, packageProgram, dtsFilePath, dtsProgram); - const r3SymbolsFile = r3SymbolsPath && packageProgram.getSourceFile(r3SymbolsPath) || null; // Parse and analyze the files. const {decorationAnalyses, switchMarkerAnalyses} = this.analyzeProgram(packageProgram, reflectionHost, rootDirs, isCore); - console.time(entryPoint.name + '(rendering)'); + console.time(`${entryPoint.name} (rendering)`); // Transform the source files and source maps. const renderer = this.getRenderer( - format, packageProgram, reflectionHost, isCore, r3SymbolsFile, transformDts); + format, packageProgram, reflectionHost, isCore, r3SymbolsFile, r3SymbolsDtsFile, + transformDts); const renderedFiles = renderer.renderProgram(packageProgram, decorationAnalyses, switchMarkerAnalyses); - console.timeEnd(entryPoint.name + '(rendering)'); + console.timeEnd(`${entryPoint.name} (rendering)`); // Write out all the transformed files. renderedFiles.forEach(file => this.writeFile(file)); @@ -126,16 +135,19 @@ export class Transformer { getRenderer( format: string, program: ts.Program, host: NgccReflectionHost, isCore: boolean, - rewriteCoreImportsTo: ts.SourceFile|null, transformDts: boolean): Renderer { + rewriteCoreImportsTo: ts.SourceFile|null, rewriteDtsCoreImportsTo: ts.SourceFile|null, + transformDts: boolean): Renderer { switch (format) { case 'esm2015': case 'fesm2015': return new EsmRenderer( - host, isCore, rewriteCoreImportsTo, this.sourcePath, this.targetPath, transformDts); + host, isCore, rewriteCoreImportsTo, rewriteDtsCoreImportsTo, this.sourcePath, + this.targetPath, transformDts); case 'esm5': case 'fesm5': return new Esm5Renderer( - host, isCore, rewriteCoreImportsTo, this.sourcePath, this.targetPath, transformDts); + host, isCore, rewriteCoreImportsTo, rewriteDtsCoreImportsTo, this.sourcePath, + this.targetPath, transformDts); default: throw new Error(`Renderer for "${format}" not yet implemented.`); } @@ -162,8 +174,8 @@ export class Transformer { writeFileSync(file.path, file.contents, 'utf8'); } - findR3SymbolsPath(directory: string): string|null { - const r3SymbolsFilePath = resolve(directory, 'r3_symbols.js'); + findR3SymbolsPath(directory: string, fileName: string): string|null { + const r3SymbolsFilePath = resolve(directory, fileName); if (existsSync(r3SymbolsFilePath)) { return r3SymbolsFilePath; } @@ -181,7 +193,7 @@ export class Transformer { }); for (const subDirectory of subDirectories) { - const r3SymbolsFilePath = this.findR3SymbolsPath(resolve(directory, subDirectory)); + const r3SymbolsFilePath = this.findR3SymbolsPath(resolve(directory, subDirectory), fileName); if (r3SymbolsFilePath) { return r3SymbolsFilePath; } diff --git a/packages/compiler-cli/src/ngcc/src/rendering/esm5_renderer.ts b/packages/compiler-cli/src/ngcc/src/rendering/esm5_renderer.ts index 3d8c70e39679..85c9cd434f99 100644 --- a/packages/compiler-cli/src/ngcc/src/rendering/esm5_renderer.ts +++ b/packages/compiler-cli/src/ngcc/src/rendering/esm5_renderer.ts @@ -14,9 +14,12 @@ import {EsmRenderer} from './esm_renderer'; export class Esm5Renderer extends EsmRenderer { constructor( protected host: NgccReflectionHost, protected isCore: boolean, - protected rewriteCoreImportsTo: ts.SourceFile|null, protected sourcePath: string, + protected rewriteCoreImportsTo: ts.SourceFile|null, + protected rewriteDtsCoreImportsTo: ts.SourceFile|null, protected sourcePath: string, protected targetPath: string, transformDts: boolean) { - super(host, isCore, rewriteCoreImportsTo, sourcePath, targetPath, transformDts); + super( + host, isCore, rewriteCoreImportsTo, rewriteDtsCoreImportsTo, sourcePath, targetPath, + transformDts); } /** diff --git a/packages/compiler-cli/src/ngcc/src/rendering/esm_renderer.ts b/packages/compiler-cli/src/ngcc/src/rendering/esm_renderer.ts index aa59ab164037..2c911675125e 100644 --- a/packages/compiler-cli/src/ngcc/src/rendering/esm_renderer.ts +++ b/packages/compiler-cli/src/ngcc/src/rendering/esm_renderer.ts @@ -14,9 +14,12 @@ import {Renderer} from './renderer'; export class EsmRenderer extends Renderer { constructor( protected host: NgccReflectionHost, protected isCore: boolean, - protected rewriteCoreImportsTo: ts.SourceFile|null, protected sourcePath: string, + protected rewriteCoreImportsTo: ts.SourceFile|null, + protected rewriteDtsCoreImportsTo: ts.SourceFile|null, protected sourcePath: string, protected targetPath: string, transformDts: boolean) { - super(host, isCore, rewriteCoreImportsTo, sourcePath, targetPath, transformDts); + super( + host, isCore, rewriteCoreImportsTo, rewriteDtsCoreImportsTo, sourcePath, targetPath, + transformDts); } /** diff --git a/packages/compiler-cli/src/ngcc/src/rendering/renderer.ts b/packages/compiler-cli/src/ngcc/src/rendering/renderer.ts index 54f2cacdd10f..838ae26a14cc 100644 --- a/packages/compiler-cli/src/ngcc/src/rendering/renderer.ts +++ b/packages/compiler-cli/src/ngcc/src/rendering/renderer.ts @@ -56,7 +56,8 @@ interface DtsClassInfo { export abstract class Renderer { constructor( protected host: NgccReflectionHost, protected isCore: boolean, - protected rewriteCoreImportsTo: ts.SourceFile|null, protected sourcePath: string, + protected rewriteCoreImportsTo: ts.SourceFile|null, + protected rewriteDtsCoreImportsTo: ts.SourceFile|null, protected sourcePath: string, protected targetPath: string, protected transformDts: boolean) {} renderProgram( @@ -142,7 +143,7 @@ export abstract class Renderer { }); this.addImports( - outputText, importManager.getAllImports(dtsFile.fileName, this.rewriteCoreImportsTo)); + outputText, importManager.getAllImports(dtsFile.fileName, this.rewriteDtsCoreImportsTo)); return this.renderSourceAndMap(dtsFile, input, outputText); } diff --git a/packages/compiler-cli/src/ngcc/test/rendering/esm2015_renderer_spec.ts b/packages/compiler-cli/src/ngcc/test/rendering/esm2015_renderer_spec.ts index d1ba2c9f680c..a0f4edb68f42 100644 --- a/packages/compiler-cli/src/ngcc/test/rendering/esm2015_renderer_spec.ts +++ b/packages/compiler-cli/src/ngcc/test/rendering/esm2015_renderer_spec.ts @@ -23,7 +23,7 @@ function setup(file: {name: string, contents: string}, transformDts: boolean = f const decorationAnalyses = new DecorationAnalyzer(program.getTypeChecker(), host, [''], false).analyzeProgram(program); const switchMarkerAnalyses = new SwitchMarkerAnalyzer(host).analyzeProgram(program); - const renderer = new EsmRenderer(host, false, null, dir, dir, false); + const renderer = new EsmRenderer(host, false, null, null, dir, dir, false); return {host, program, sourceFile, renderer, decorationAnalyses, switchMarkerAnalyses}; } diff --git a/packages/compiler-cli/src/ngcc/test/rendering/esm5_renderer_spec.ts b/packages/compiler-cli/src/ngcc/test/rendering/esm5_renderer_spec.ts index 3cad53c8fc5e..81674350bf88 100644 --- a/packages/compiler-cli/src/ngcc/test/rendering/esm5_renderer_spec.ts +++ b/packages/compiler-cli/src/ngcc/test/rendering/esm5_renderer_spec.ts @@ -20,7 +20,7 @@ function setup(file: {name: string, contents: string}) { const decorationAnalyses = new DecorationAnalyzer(program.getTypeChecker(), host, [''], false).analyzeProgram(program); const switchMarkerAnalyses = new SwitchMarkerAnalyzer(host).analyzeProgram(program); - const renderer = new Esm5Renderer(host, false, null, '', '', false); + const renderer = new Esm5Renderer(host, false, null, null, '', '', false); return {host, program, sourceFile, renderer, decorationAnalyses, switchMarkerAnalyses}; } diff --git a/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts b/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts index 1fc8c6da8e1c..1fa2665f0ce8 100644 --- a/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts +++ b/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts @@ -19,7 +19,7 @@ import {Renderer} from '../../src/rendering/renderer'; class TestRenderer extends Renderer { constructor( host: Esm2015ReflectionHost, isCore: boolean, rewriteCoreImportsTo: ts.SourceFile|null) { - super(host, isCore, rewriteCoreImportsTo, '/src', '/dist', false); + super(host, isCore, rewriteCoreImportsTo, null, '/src', '/dist', false); } addImports(output: MagicString, imports: {name: string, as: string}[]) { output.prepend('\n// ADD IMPORTS\n'); From 9811ee4ddd92b6187d5a56d350c73c7b6166e842 Mon Sep 17 00:00:00 2001 From: JoostK Date: Mon, 12 Nov 2018 17:36:59 +0100 Subject: [PATCH 3/4] =?UTF-8?q?fixup!=20fix(ivy):=20prevent=20ngcc=20from?= =?UTF-8?q?=20referencing=20missing=20=C9=B5setClassMetadata?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/compiler-cli/src/ngtsc/metadata/src/resolver.ts | 2 +- packages/compiler-cli/src/ngtsc/util/src/path.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/compiler-cli/src/ngtsc/metadata/src/resolver.ts b/packages/compiler-cli/src/ngtsc/metadata/src/resolver.ts index 60675469ead4..7c5d0e78894c 100644 --- a/packages/compiler-cli/src/ngtsc/metadata/src/resolver.ts +++ b/packages/compiler-cli/src/ngtsc/metadata/src/resolver.ts @@ -17,7 +17,7 @@ import * as ts from 'typescript'; import {ClassMemberKind, ReflectionHost} from '../../host'; -const TS_DTS_JS_EXTENSION = /(\.d)?\.ts|\.js$/; +const TS_DTS_JS_EXTENSION = /(?:\.d)?\.ts$|\.js$/; /** * Represents a value which cannot be determined statically. diff --git a/packages/compiler-cli/src/ngtsc/util/src/path.ts b/packages/compiler-cli/src/ngtsc/util/src/path.ts index 6740d7d8a0b5..4c5d11c55f09 100644 --- a/packages/compiler-cli/src/ngtsc/util/src/path.ts +++ b/packages/compiler-cli/src/ngtsc/util/src/path.ts @@ -10,7 +10,7 @@ import * as path from 'path'; -const TS_DTS_JS_EXTENSION = /(\.d)?\.ts|\.js$/; +const TS_DTS_JS_EXTENSION = /(?:\.d)?\.ts$|\.js$/; export function relativePathBetween(from: string, to: string): string|null { let relative = path.posix.relative(path.dirname(from), to).replace(TS_DTS_JS_EXTENSION, ''); From 789d32326b4e95e3a04e77a1f3b2de7c430c1f13 Mon Sep 17 00:00:00 2001 From: JoostK Date: Mon, 12 Nov 2018 20:05:49 +0100 Subject: [PATCH 4/4] fixup! fix(ivy): let ngcc transform @angular/core typings with relative imports --- integration/ngcc/test.sh | 6 +++ .../src/ngcc/src/packages/bundle.ts | 31 +++++++++++++++ .../src/ngcc/src/packages/transformer.ts | 38 +++++++++---------- .../src/ngcc/src/rendering/esm5_renderer.ts | 11 ++---- .../src/ngcc/src/rendering/esm_renderer.ts | 11 ++---- .../src/ngcc/src/rendering/renderer.ts | 19 +++++----- .../test/rendering/esm2015_renderer_spec.ts | 4 +- .../ngcc/test/rendering/esm5_renderer_spec.ts | 4 +- .../src/ngcc/test/rendering/renderer_spec.ts | 17 +++++---- 9 files changed, 89 insertions(+), 52 deletions(-) create mode 100644 packages/compiler-cli/src/ngcc/src/packages/bundle.ts diff --git a/integration/ngcc/test.sh b/integration/ngcc/test.sh index d46ad3201d3e..efa8901f7aa0 100755 --- a/integration/ngcc/test.sh +++ b/integration/ngcc/test.sh @@ -33,6 +33,12 @@ ivy-ngcc grep "ApplicationModule.ngModuleDef = ɵngcc0.defineNgModule" node_modules/@angular/core/esm5/src/application_module.js if [[ $? != 0 ]]; then exit 1; fi +# Did it transform @angular/core typing files correctly? + grep "import [*] as ɵngcc0 from './r3_symbols';" node_modules/@angular/core/src/application_module.d.ts + if [[ $? != 0 ]]; then exit 1; fi + grep "static ngInjectorDef: ɵngcc0.InjectorDef;" node_modules/@angular/core/src/application_module.d.ts + if [[ $? != 0 ]]; then exit 1; fi + # Can it be safely run again (as a noop)? ivy-ngcc diff --git a/packages/compiler-cli/src/ngcc/src/packages/bundle.ts b/packages/compiler-cli/src/ngcc/src/packages/bundle.ts new file mode 100644 index 000000000000..872e8ad213f1 --- /dev/null +++ b/packages/compiler-cli/src/ngcc/src/packages/bundle.ts @@ -0,0 +1,31 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as ts from 'typescript'; + +/** + * A bundle represents the currently compiled entry point format, containing + * information that is necessary for compiling @angular/core with ngcc. + */ +export interface BundleInfo { + isCore: boolean; + isFlat: boolean; + rewriteCoreImportsTo: ts.SourceFile|null; + rewriteCoreDtsImportsTo: ts.SourceFile|null; +} + +export function createBundleInfo( + isCore: boolean, rewriteCoreImportsTo: ts.SourceFile | null, + rewriteCoreDtsImportsTo: ts.SourceFile | null): BundleInfo { + return { + isCore, + isFlat: rewriteCoreImportsTo === null, + rewriteCoreImportsTo: rewriteCoreImportsTo, + rewriteCoreDtsImportsTo: rewriteCoreDtsImportsTo, + }; +} diff --git a/packages/compiler-cli/src/ngcc/src/packages/transformer.ts b/packages/compiler-cli/src/ngcc/src/packages/transformer.ts index 0a8ccdcc28ad..0b13e8a83201 100644 --- a/packages/compiler-cli/src/ngcc/src/packages/transformer.ts +++ b/packages/compiler-cli/src/ngcc/src/packages/transformer.ts @@ -20,6 +20,7 @@ import {EsmRenderer} from '../rendering/esm_renderer'; import {FileInfo, Renderer} from '../rendering/renderer'; import {checkMarkerFile, writeMarkerFile} from './build_marker'; +import {BundleInfo, createBundleInfo} from './bundle'; import {EntryPoint, EntryPointFormat} from './entry_point'; /** @@ -76,16 +77,22 @@ export class Transformer { const packageProgram = ts.createProgram(rootPaths, options, host); const r3SymbolsFile = r3SymbolsPath && packageProgram.getSourceFile(r3SymbolsPath) || null; - console.time(`${entryPoint.name} (dtsMapper creation)`); + // Create the program for processing DTS files if enabled for this format. const dtsFilePath = entryPoint.typings; - const r3SymbolsDtsPath = - isCore ? this.findR3SymbolsPath(dirname(dtsFilePath), 'r3_symbols.d.ts') : null; - const rootDtsPaths = r3SymbolsDtsPath ? [dtsFilePath, r3SymbolsDtsPath] : [dtsFilePath]; - const dtsProgram = transformDts ? ts.createProgram(rootDtsPaths, options, host) : null; - const r3SymbolsDtsFile = - dtsProgram && r3SymbolsDtsPath && dtsProgram.getSourceFile(r3SymbolsDtsPath) || null; - console.timeEnd(`${entryPoint.name} (dtsMapper creation)`); + let dtsProgram: ts.Program|null = null; + let r3SymbolsDtsFile: ts.SourceFile|null = null; + if (transformDts) { + console.time(`${entryPoint.name} (dtsMapper creation)`); + const r3SymbolsDtsPath = + isCore ? this.findR3SymbolsPath(dirname(dtsFilePath), 'r3_symbols.d.ts') : null; + const rootDtsPaths = r3SymbolsDtsPath ? [dtsFilePath, r3SymbolsDtsPath] : [dtsFilePath]; + + dtsProgram = ts.createProgram(rootDtsPaths, options, host); + r3SymbolsDtsFile = r3SymbolsDtsPath && dtsProgram.getSourceFile(r3SymbolsDtsPath) || null; + console.timeEnd(`${entryPoint.name} (dtsMapper creation)`); + } + const bundle = createBundleInfo(isCore, r3SymbolsFile, r3SymbolsDtsFile); const reflectionHost = this.getHost(isCore, format, packageProgram, dtsFilePath, dtsProgram); // Parse and analyze the files. @@ -94,9 +101,7 @@ export class Transformer { console.time(`${entryPoint.name} (rendering)`); // Transform the source files and source maps. - const renderer = this.getRenderer( - format, packageProgram, reflectionHost, isCore, r3SymbolsFile, r3SymbolsDtsFile, - transformDts); + const renderer = this.getRenderer(format, packageProgram, reflectionHost, bundle, transformDts); const renderedFiles = renderer.renderProgram(packageProgram, decorationAnalyses, switchMarkerAnalyses); console.timeEnd(`${entryPoint.name} (rendering)`); @@ -134,20 +139,15 @@ export class Transformer { } getRenderer( - format: string, program: ts.Program, host: NgccReflectionHost, isCore: boolean, - rewriteCoreImportsTo: ts.SourceFile|null, rewriteDtsCoreImportsTo: ts.SourceFile|null, + format: string, program: ts.Program, host: NgccReflectionHost, bundle: BundleInfo, transformDts: boolean): Renderer { switch (format) { case 'esm2015': case 'fesm2015': - return new EsmRenderer( - host, isCore, rewriteCoreImportsTo, rewriteDtsCoreImportsTo, this.sourcePath, - this.targetPath, transformDts); + return new EsmRenderer(host, bundle, this.sourcePath, this.targetPath, transformDts); case 'esm5': case 'fesm5': - return new Esm5Renderer( - host, isCore, rewriteCoreImportsTo, rewriteDtsCoreImportsTo, this.sourcePath, - this.targetPath, transformDts); + return new Esm5Renderer(host, bundle, this.sourcePath, this.targetPath, transformDts); default: throw new Error(`Renderer for "${format}" not yet implemented.`); } diff --git a/packages/compiler-cli/src/ngcc/src/rendering/esm5_renderer.ts b/packages/compiler-cli/src/ngcc/src/rendering/esm5_renderer.ts index 85c9cd434f99..0cdf9b2bea8c 100644 --- a/packages/compiler-cli/src/ngcc/src/rendering/esm5_renderer.ts +++ b/packages/compiler-cli/src/ngcc/src/rendering/esm5_renderer.ts @@ -9,17 +9,14 @@ import * as ts from 'typescript'; import MagicString from 'magic-string'; import {NgccReflectionHost} from '../host/ngcc_host'; import {CompiledClass} from '../analysis/decoration_analyzer'; +import {BundleInfo} from '../packages/bundle'; import {EsmRenderer} from './esm_renderer'; export class Esm5Renderer extends EsmRenderer { constructor( - protected host: NgccReflectionHost, protected isCore: boolean, - protected rewriteCoreImportsTo: ts.SourceFile|null, - protected rewriteDtsCoreImportsTo: ts.SourceFile|null, protected sourcePath: string, - protected targetPath: string, transformDts: boolean) { - super( - host, isCore, rewriteCoreImportsTo, rewriteDtsCoreImportsTo, sourcePath, targetPath, - transformDts); + protected host: NgccReflectionHost, protected bundle: BundleInfo, + protected sourcePath: string, protected targetPath: string, transformDts: boolean) { + super(host, bundle, sourcePath, targetPath, transformDts); } /** diff --git a/packages/compiler-cli/src/ngcc/src/rendering/esm_renderer.ts b/packages/compiler-cli/src/ngcc/src/rendering/esm_renderer.ts index 2c911675125e..657665da212f 100644 --- a/packages/compiler-cli/src/ngcc/src/rendering/esm_renderer.ts +++ b/packages/compiler-cli/src/ngcc/src/rendering/esm_renderer.ts @@ -9,17 +9,14 @@ import * as ts from 'typescript'; import MagicString from 'magic-string'; import {NgccReflectionHost, POST_R3_MARKER, PRE_R3_MARKER, SwitchableVariableDeclaration} from '../host/ngcc_host'; import {CompiledClass} from '../analysis/decoration_analyzer'; +import {BundleInfo} from '../packages/bundle'; import {Renderer} from './renderer'; export class EsmRenderer extends Renderer { constructor( - protected host: NgccReflectionHost, protected isCore: boolean, - protected rewriteCoreImportsTo: ts.SourceFile|null, - protected rewriteDtsCoreImportsTo: ts.SourceFile|null, protected sourcePath: string, - protected targetPath: string, transformDts: boolean) { - super( - host, isCore, rewriteCoreImportsTo, rewriteDtsCoreImportsTo, sourcePath, targetPath, - transformDts); + protected host: NgccReflectionHost, protected bundle: BundleInfo, + protected sourcePath: string, protected targetPath: string, transformDts: boolean) { + super(host, bundle, sourcePath, targetPath, transformDts); } /** diff --git a/packages/compiler-cli/src/ngcc/src/rendering/renderer.ts b/packages/compiler-cli/src/ngcc/src/rendering/renderer.ts index 838ae26a14cc..7e8c7ee85f7d 100644 --- a/packages/compiler-cli/src/ngcc/src/rendering/renderer.ts +++ b/packages/compiler-cli/src/ngcc/src/rendering/renderer.ts @@ -19,6 +19,7 @@ import {translateStatement, translateType} from '../../../ngtsc/translator'; import {NgccImportManager} from './ngcc_import_manager'; import {CompiledClass, CompiledFile, DecorationAnalyses} from '../analysis/decoration_analyzer'; import {SwitchMarkerAnalyses, SwitchMarkerAnalysis} from '../analysis/switch_marker_analyzer'; +import {BundleInfo} from '../packages/bundle'; import {IMPORT_PREFIX} from '../constants'; import {NgccReflectionHost, SwitchableVariableDeclaration} from '../host/ngcc_host'; @@ -55,10 +56,9 @@ interface DtsClassInfo { */ export abstract class Renderer { constructor( - protected host: NgccReflectionHost, protected isCore: boolean, - protected rewriteCoreImportsTo: ts.SourceFile|null, - protected rewriteDtsCoreImportsTo: ts.SourceFile|null, protected sourcePath: string, - protected targetPath: string, protected transformDts: boolean) {} + protected host: NgccReflectionHost, protected bundle: BundleInfo, + protected sourcePath: string, protected targetPath: string, protected transformDts: boolean) { + } renderProgram( program: ts.Program, decorationAnalyses: DecorationAnalyses, @@ -102,7 +102,7 @@ export abstract class Renderer { if (compiledFile) { const importManager = - new NgccImportManager(!this.rewriteCoreImportsTo, this.isCore, IMPORT_PREFIX); + new NgccImportManager(this.bundle.isFlat, this.bundle.isCore, IMPORT_PREFIX); const decoratorsToRemove = new Map(); compiledFile.compiledClasses.forEach(clazz => { @@ -117,8 +117,8 @@ export abstract class Renderer { compiledFile.sourceFile); this.addImports( - outputText, - importManager.getAllImports(compiledFile.sourceFile.fileName, this.rewriteCoreImportsTo)); + outputText, importManager.getAllImports( + compiledFile.sourceFile.fileName, this.bundle.rewriteCoreImportsTo)); // TODO: remove contructor param metadata and property decorators (we need info from the // handlers to do this) @@ -131,7 +131,7 @@ export abstract class Renderer { renderDtsFile(dtsFile: ts.SourceFile, dtsClasses: DtsClassInfo[]): FileInfo[] { const input = this.extractSourceMap(dtsFile); const outputText = new MagicString(input.source); - const importManager = new NgccImportManager(false, this.isCore, IMPORT_PREFIX); + const importManager = new NgccImportManager(false, this.bundle.isCore, IMPORT_PREFIX); dtsClasses.forEach(dtsClass => { const endOfClass = dtsClass.dtsDeclaration.getEnd(); @@ -143,7 +143,8 @@ export abstract class Renderer { }); this.addImports( - outputText, importManager.getAllImports(dtsFile.fileName, this.rewriteDtsCoreImportsTo)); + outputText, + importManager.getAllImports(dtsFile.fileName, this.bundle.rewriteCoreDtsImportsTo)); return this.renderSourceAndMap(dtsFile, input, outputText); } diff --git a/packages/compiler-cli/src/ngcc/test/rendering/esm2015_renderer_spec.ts b/packages/compiler-cli/src/ngcc/test/rendering/esm2015_renderer_spec.ts index a0f4edb68f42..7d51ce172eea 100644 --- a/packages/compiler-cli/src/ngcc/test/rendering/esm2015_renderer_spec.ts +++ b/packages/compiler-cli/src/ngcc/test/rendering/esm2015_renderer_spec.ts @@ -12,6 +12,7 @@ import MagicString from 'magic-string'; import {makeProgram} from '../helpers/utils'; import {DecorationAnalyzer} from '../../src/analysis/decoration_analyzer'; import {SwitchMarkerAnalyzer} from '../../src/analysis/switch_marker_analyzer'; +import {createBundleInfo} from '../../src/packages/bundle'; import {Esm2015ReflectionHost} from '../../src/host/esm2015_host'; import {EsmRenderer} from '../../src/rendering/esm_renderer'; @@ -23,7 +24,8 @@ function setup(file: {name: string, contents: string}, transformDts: boolean = f const decorationAnalyses = new DecorationAnalyzer(program.getTypeChecker(), host, [''], false).analyzeProgram(program); const switchMarkerAnalyses = new SwitchMarkerAnalyzer(host).analyzeProgram(program); - const renderer = new EsmRenderer(host, false, null, null, dir, dir, false); + const bundle = createBundleInfo(false, null, null); + const renderer = new EsmRenderer(host, bundle, dir, dir, false); return {host, program, sourceFile, renderer, decorationAnalyses, switchMarkerAnalyses}; } diff --git a/packages/compiler-cli/src/ngcc/test/rendering/esm5_renderer_spec.ts b/packages/compiler-cli/src/ngcc/test/rendering/esm5_renderer_spec.ts index 81674350bf88..c04bbee6106a 100644 --- a/packages/compiler-cli/src/ngcc/test/rendering/esm5_renderer_spec.ts +++ b/packages/compiler-cli/src/ngcc/test/rendering/esm5_renderer_spec.ts @@ -10,6 +10,7 @@ import MagicString from 'magic-string'; import {makeProgram, getDeclaration} from '../helpers/utils'; import {DecorationAnalyzer} from '../../src/analysis/decoration_analyzer'; import {SwitchMarkerAnalyzer} from '../../src/analysis/switch_marker_analyzer'; +import {createBundleInfo} from '../../src/packages/bundle'; import {Esm5ReflectionHost} from '../../src/host/esm5_host'; import {Esm5Renderer} from '../../src/rendering/esm5_renderer'; @@ -20,7 +21,8 @@ function setup(file: {name: string, contents: string}) { const decorationAnalyses = new DecorationAnalyzer(program.getTypeChecker(), host, [''], false).analyzeProgram(program); const switchMarkerAnalyses = new SwitchMarkerAnalyzer(host).analyzeProgram(program); - const renderer = new Esm5Renderer(host, false, null, null, '', '', false); + const bundle = createBundleInfo(false, null, null); + const renderer = new Esm5Renderer(host, bundle, '', '', false); return {host, program, sourceFile, renderer, decorationAnalyses, switchMarkerAnalyses}; } diff --git a/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts b/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts index 1fa2665f0ce8..e63fa81f8931 100644 --- a/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts +++ b/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts @@ -13,13 +13,13 @@ import {fromObject, generateMapFileComment} from 'convert-source-map'; import {makeProgram} from '../helpers/utils'; import {CompiledClass, DecorationAnalyzer} from '../../src/analysis/decoration_analyzer'; import {SwitchMarkerAnalyzer} from '../../src/analysis/switch_marker_analyzer'; +import {BundleInfo, createBundleInfo} from '../../src/packages/bundle'; import {Esm2015ReflectionHost} from '../../src/host/esm2015_host'; import {Renderer} from '../../src/rendering/renderer'; class TestRenderer extends Renderer { - constructor( - host: Esm2015ReflectionHost, isCore: boolean, rewriteCoreImportsTo: ts.SourceFile|null) { - super(host, isCore, rewriteCoreImportsTo, null, '/src', '/dist', false); + constructor(host: Esm2015ReflectionHost, bundle: BundleInfo) { + super(host, bundle, '/src', '/dist', false); } addImports(output: MagicString, imports: {name: string, as: string}[]) { output.prepend('\n// ADD IMPORTS\n'); @@ -42,14 +42,15 @@ function createTestRenderer( files: {name: string, contents: string}[], options: {isCore?: boolean, rewriteCoreImportsTo?: string} = {}) { const program = makeProgram(...files); - const host = new Esm2015ReflectionHost(options.isCore || false, program.getTypeChecker()); + const rewriteCoreImportsTo = + options.rewriteCoreImportsTo ? program.getSourceFile(options.rewriteCoreImportsTo) ! : null; + const bundle = createBundleInfo(options.isCore || false, rewriteCoreImportsTo, null); + const host = new Esm2015ReflectionHost(bundle.isCore, program.getTypeChecker()); const decorationAnalyses = - new DecorationAnalyzer(program.getTypeChecker(), host, [''], options.isCore || false) + new DecorationAnalyzer(program.getTypeChecker(), host, [''], bundle.isCore) .analyzeProgram(program); const switchMarkerAnalyses = new SwitchMarkerAnalyzer(host).analyzeProgram(program); - const rewriteCoreImportsTo = - options.rewriteCoreImportsTo ? program.getSourceFile(options.rewriteCoreImportsTo) ! : null; - const renderer = new TestRenderer(host, options.isCore || false, rewriteCoreImportsTo); + const renderer = new TestRenderer(host, bundle); spyOn(renderer, 'addImports').and.callThrough(); spyOn(renderer, 'addDefinitions').and.callThrough(); spyOn(renderer, 'removeDecorators').and.callThrough();