From 126e2facb1d1182138cbc0eb04ddcd678cca924e Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Thu, 10 Oct 2024 19:29:00 +0200 Subject: [PATCH 1/3] refactor(compiler): add logic to generate the HMR initializer Adds the logic that will generate the `import` expression that will initializer HMR for a specific component. --- packages/compiler/src/compiler.ts | 1 + .../compiler/src/render3/r3_hmr_compiler.ts | 67 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 packages/compiler/src/render3/r3_hmr_compiler.ts diff --git a/packages/compiler/src/compiler.ts b/packages/compiler/src/compiler.ts index 2ed8439c2586..4485488a3b0f 100644 --- a/packages/compiler/src/compiler.ts +++ b/packages/compiler/src/compiler.ts @@ -173,6 +173,7 @@ export { compileOpaqueAsyncClassMetadata, } from './render3/r3_class_metadata_compiler'; export {compileClassDebugInfo, R3ClassDebugInfo} from './render3/r3_class_debug_info_compiler'; +export {compileClassHmrInitializer, R3HmrInitializerMetadata} from './render3/r3_hmr_compiler'; export { compileFactoryFunction, R3DependencyMetadata, diff --git a/packages/compiler/src/render3/r3_hmr_compiler.ts b/packages/compiler/src/render3/r3_hmr_compiler.ts new file mode 100644 index 000000000000..5e3ae3a30965 --- /dev/null +++ b/packages/compiler/src/render3/r3_hmr_compiler.ts @@ -0,0 +1,67 @@ +/*! + * @license + * Copyright Google LLC 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.dev/license + */ + +import * as o from '../output/output_ast'; +import {Identifiers as R3} from './r3_identifiers'; +import {devOnlyGuardedExpression} from './util'; + +/** Metadata necessary to compile the HMR initializer call. */ +export interface R3HmrInitializerMetadata { + /** Component class for which HMR is being enabled. */ + type: o.Expression; + + /** Name of the component class. */ + className: string; + + /** File path of the component class. */ + filePath: string; + + /** + * Timestamp when the compilation took place. + * Necessary to invalidate the browser cache. + */ + timestamp: string; +} + +/** Compiles the HMR initializer expression. */ +export function compileClassHmrInitializer(meta: R3HmrInitializerMetadata): o.Expression { + const id = encodeURIComponent(`${meta.filePath}@${meta.className}`); + const timestamp = encodeURIComponent(meta.timestamp); + const url = `/@ng/component?c=${id}&t=${timestamp}`; + const moduleName = 'm'; + const dataName = 'd'; + + // ɵɵreplaceMetadata(Comp, m.default); + const replaceMetadata = o + .importExpr(R3.replaceMetadata) + .callFn([meta.type, o.variable(moduleName).prop('default')]); + + // (m) => ɵɵreplaceMetadata(...) + const replaceCallback = o.arrowFn([new o.FnParam(moduleName)], replaceMetadata); + + // import(url).then(() => replaceMetadata(...)); + const dynamicImport = new o.DynamicImportExpr(url).prop('then').callFn([replaceCallback]); + + // (d) => { if (d.id === ) { replaceMetadata(...) } } + const listenerCallback = o.arrowFn( + [new o.FnParam(dataName)], + [o.ifStmt(o.variable(dataName).prop('id').equals(o.literal(id)), [dynamicImport.toStmt()])], + ); + + // import.meta.hot + const hotRead = o.variable('import').prop('meta').prop('hot'); + + // import.meta.hot.on('angular:component-update', () => ...); + const hotListener = hotRead + .clone() + .prop('on') + .callFn([o.literal('angular:component-update'), listenerCallback]); + + // import.meta.hot && import.meta.hot.on(...) + return o.arrowFn([], [devOnlyGuardedExpression(hotRead.and(hotListener)).toStmt()]).callFn([]); +} From f6d1e52750359314749e427bb56ff2697d1e68cf Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Thu, 10 Oct 2024 20:48:41 +0200 Subject: [PATCH 2/3] refactor(compiler-cli): output HMR initializer code Adds the logic to the compiler that will output the HMR initializer code for each component, if enabled. --- packages/bazel/src/ngc-wrapped/index.ts | 1 + .../src/ngtsc/annotations/common/src/util.ts | 5 ++ .../annotations/component/src/handler.ts | 16 +++++ .../ngtsc/annotations/component/src/hmr.ts | 43 +++++++++++++ .../annotations/component/src/metadata.ts | 2 + .../component/test/component_spec.ts | 1 + .../src/ngtsc/core/api/src/options.ts | 7 +++ .../src/ngtsc/core/src/compiler.ts | 3 + .../compiler-cli/test/ngtsc/ngtsc_spec.ts | 63 +++++++++++++++++++ 9 files changed, 141 insertions(+) create mode 100644 packages/compiler-cli/src/ngtsc/annotations/component/src/hmr.ts diff --git a/packages/bazel/src/ngc-wrapped/index.ts b/packages/bazel/src/ngc-wrapped/index.ts index 884a23aeaf31..72a687f58fe0 100644 --- a/packages/bazel/src/ngc-wrapped/index.ts +++ b/packages/bazel/src/ngc-wrapped/index.ts @@ -92,6 +92,7 @@ export async function runOneBuild( 'onlyExplicitDeferDependencyImports', 'generateExtraImportsInLocalMode', '_enableLetSyntax', + '_enableHmr', ]); const userOverrides = Object.entries(userOptions) diff --git a/packages/compiler-cli/src/ngtsc/annotations/common/src/util.ts b/packages/compiler-cli/src/ngtsc/annotations/common/src/util.ts index 18a09e700fe7..533fad06ac13 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/common/src/util.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/common/src/util.ts @@ -413,6 +413,7 @@ export function compileResults( additionalFields: CompileResult[] | null, deferrableImports: Set | null, debugInfo: Statement | null = null, + hmrInitializer: Statement | null = null, ): CompileResult[] { const statements = def.statements; @@ -424,6 +425,10 @@ export function compileResults( statements.push(debugInfo); } + if (hmrInitializer !== null) { + statements.push(hmrInitializer); + } + const results = [ fac, { diff --git a/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts b/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts index a23dc56fa8a6..8f2a7943318b 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts @@ -10,6 +10,7 @@ import { AnimationTriggerNames, BoundTarget, compileClassDebugInfo, + compileClassHmrInitializer, compileComponentClassMetadata, compileComponentDeclareClassMetadata, compileComponentFromMetadata, @@ -179,6 +180,7 @@ import { } from './util'; import {getTemplateDiagnostics} from '../../../typecheck'; import {JitDeclarationRegistry} from '../../common/src/jit_declaration_registry'; +import {extractHmrInitializerMeta} from './hmr'; const EMPTY_ARRAY: any[] = []; @@ -255,6 +257,7 @@ export class ComponentDecoratorHandler private readonly jitDeclarationRegistry: JitDeclarationRegistry, private readonly i18nPreserveSignificantWhitespace: boolean, private readonly strictStandalone: boolean, + private readonly enableHmr: boolean, ) { this.extractTemplateOptions = { enableI18nLegacyMessageIdFormat: this.enableI18nLegacyMessageIdFormat, @@ -872,6 +875,9 @@ export class ComponentDecoratorHandler this.rootDirs, /* forbidOrphanRenderering */ this.forbidOrphanRendering, ), + hmrInitializerMeta: this.enableHmr + ? extractHmrInitializerMeta(node, this.reflector, this.rootDirs) + : null, template, providersRequiringFactory, viewProvidersRequiringFactory, @@ -1613,6 +1619,10 @@ export class ComponentDecoratorHandler analysis.classDebugInfo !== null ? compileClassDebugInfo(analysis.classDebugInfo).toStmt() : null; + const hmrInitializer = + analysis.hmrInitializerMeta !== null + ? compileClassHmrInitializer(analysis.hmrInitializerMeta).toStmt() + : null; const deferrableImports = this.deferredSymbolTracker.getDeferrableImportDecls(); return compileResults( fac, @@ -1622,6 +1632,7 @@ export class ComponentDecoratorHandler inputTransformFields, deferrableImports, debugInfo, + hmrInitializer, ); } @@ -1695,6 +1706,10 @@ export class ComponentDecoratorHandler analysis.classDebugInfo !== null ? compileClassDebugInfo(analysis.classDebugInfo).toStmt() : null; + const hmrInitializer = + analysis.hmrInitializerMeta !== null + ? compileClassHmrInitializer(analysis.hmrInitializerMeta).toStmt() + : null; const deferrableImports = this.deferredSymbolTracker.getDeferrableImportDecls(); return compileResults( fac, @@ -1704,6 +1719,7 @@ export class ComponentDecoratorHandler inputTransformFields, deferrableImports, debugInfo, + hmrInitializer, ); } diff --git a/packages/compiler-cli/src/ngtsc/annotations/component/src/hmr.ts b/packages/compiler-cli/src/ngtsc/annotations/component/src/hmr.ts new file mode 100644 index 000000000000..4c510ba7c156 --- /dev/null +++ b/packages/compiler-cli/src/ngtsc/annotations/component/src/hmr.ts @@ -0,0 +1,43 @@ +/*! + * @license + * Copyright Google LLC 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.dev/license + */ + +import {R3HmrInitializerMetadata, WrappedNodeExpr} from '@angular/compiler'; +import {DeclarationNode, ReflectionHost} from '../../../reflection'; +import {relative} from 'path'; + +/** + * Extracts the metadata necessary to generate an HMR initializer. + */ +export function extractHmrInitializerMeta( + clazz: DeclarationNode, + reflection: ReflectionHost, + rootDirs: readonly string[], +): R3HmrInitializerMetadata | null { + if (!reflection.isClass(clazz)) { + return null; + } + + // Attempt to generate a project-relative path before falling back to the full path. + let filePath = clazz.getSourceFile().fileName; + for (const rootDir of rootDirs) { + const relativePath = relative(rootDir, filePath); + if (!relativePath.startsWith('..')) { + filePath = relativePath; + break; + } + } + + const meta: R3HmrInitializerMetadata = { + type: new WrappedNodeExpr(clazz.name), + className: clazz.name.text, + timestamp: Date.now() + '', + filePath, + }; + + return meta; +} diff --git a/packages/compiler-cli/src/ngtsc/annotations/component/src/metadata.ts b/packages/compiler-cli/src/ngtsc/annotations/component/src/metadata.ts index bf0ff585e2cc..8f02d784a648 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/component/src/metadata.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/component/src/metadata.ts @@ -12,6 +12,7 @@ import { DeferBlockDepsEmitMode, R3ClassDebugInfo, R3ClassMetadata, + R3HmrInitializerMetadata, R3ComponentMetadata, R3DeferPerBlockDependency, R3DeferPerComponentDependency, @@ -56,6 +57,7 @@ export interface ComponentAnalysisData { template: ParsedTemplateWithSource; classMetadata: R3ClassMetadata | null; classDebugInfo: R3ClassDebugInfo | null; + hmrInitializerMeta: R3HmrInitializerMetadata | null; inputs: ClassPropertyMapping; inputFieldNamesFromMetadataArray: Set; diff --git a/packages/compiler-cli/src/ngtsc/annotations/component/test/component_spec.ts b/packages/compiler-cli/src/ngtsc/annotations/component/test/component_spec.ts index 39a71408fd07..9a016e6bb471 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/component/test/component_spec.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/component/test/component_spec.ts @@ -156,6 +156,7 @@ function setup( jitDeclarationRegistry, /* i18nPreserveSignificantWhitespace */ true, /* strictStandalone */ false, + /* enableHmr */ false, ); return {reflectionHost, handler, resourceLoader, metaRegistry}; } diff --git a/packages/compiler-cli/src/ngtsc/core/api/src/options.ts b/packages/compiler-cli/src/ngtsc/core/api/src/options.ts index b3b7823174dc..e87fdb71b0d0 100644 --- a/packages/compiler-cli/src/ngtsc/core/api/src/options.ts +++ b/packages/compiler-cli/src/ngtsc/core/api/src/options.ts @@ -113,6 +113,13 @@ export interface InternalOptions { * @internal */ _angularCoreVersion?: string; + + /** + * Whether to enable the necessary code generation for hot module reloading. + * + * @internal + */ + _enableHmr?: boolean; } /** diff --git a/packages/compiler-cli/src/ngtsc/core/src/compiler.ts b/packages/compiler-cli/src/ngtsc/core/src/compiler.ts index 9353ee435915..765d9dc7e7fb 100644 --- a/packages/compiler-cli/src/ngtsc/core/src/compiler.ts +++ b/packages/compiler-cli/src/ngtsc/core/src/compiler.ts @@ -390,6 +390,7 @@ export class NgCompiler { private readonly enableBlockSyntax: boolean; private readonly enableLetSyntax: boolean; private readonly angularCoreVersion: string | null; + private readonly enableHmr: boolean; /** * `NgCompiler` can be reused for multiple compilations (for resource-only changes), and each @@ -462,6 +463,7 @@ export class NgCompiler { this.enableBlockSyntax = options['_enableBlockSyntax'] ?? true; this.enableLetSyntax = options['_enableLetSyntax'] ?? true; this.angularCoreVersion = options['_angularCoreVersion'] ?? null; + this.enableHmr = !!options['_enableHmr']; this.constructionDiagnostics.push( ...this.adapter.constructionDiagnostics, ...verifyCompatibleTypeCheckOptions(this.options), @@ -1463,6 +1465,7 @@ export class NgCompiler { jitDeclarationRegistry, this.options.i18nPreserveWhitespaceForLegacyExtraction ?? true, !!this.options.strictStandalone, + this.enableHmr, ), // TODO(alxhub): understand why the cast here is necessary (something to do with `null` diff --git a/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts b/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts index 844cca4aabb7..f2646f8c538f 100644 --- a/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts +++ b/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts @@ -10519,6 +10519,69 @@ runInEachFileSystem((os: string) => { }); }); + describe('HMR initializer', () => { + it('should not generate an HMR initializer by default', () => { + env.write( + 'test.ts', + ` + import {Component} from '@angular/core'; + + @Component({ + selector: 'cmp', + template: 'hello', + standalone: true, + }) + export class Cmp {} + `, + ); + + env.driveMain(); + + const jsContents = env.getContents('test.js'); + expect(jsContents).not.toContain('import.meta.hot'); + expect(jsContents).not.toContain('replaceMetadata'); + }); + + it('should generate an HMR initializer when enabled', () => { + env.write( + 'tsconfig.json', + JSON.stringify({ + extends: './tsconfig-base.json', + angularCompilerOptions: { + _enableHmr: true, + }, + }), + ); + + env.write( + 'test.ts', + ` + import {Component} from '@angular/core'; + + @Component({ + selector: 'cmp', + template: 'hello', + standalone: true, + }) + export class Cmp {} + `, + ); + + env.driveMain(); + + const jsContents = env.getContents('test.js'); + + // We need a regex match here, because the file path changes based on + // the file system and the timestamp will be different for each test run. + expect(jsContents).toMatch( + /import\.meta\.hot && import\.meta\.hot\.on\("angular:component-update", d => { if \(d\.id == ".*test\.ts%40Cmp"\) {/, + ); + expect(jsContents).toMatch( + /import\("\/@ng\/component\?c=.*test\.ts%40Cmp&t=\d+"\).then\(m => i0\.ɵɵreplaceMetadata\(Cmp, m\.default\)\);/, + ); + }); + }); + describe('tsickle compatibility', () => { it('should preserve fileoverview comments', () => { env.write( From 4f683078ebc02f3c27af5d1874cb4f2b29f890cc Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Thu, 10 Oct 2024 21:17:16 +0200 Subject: [PATCH 3/3] fix(compiler-cli): incorrectly generating relative file paths on case-insensitive platforms We're using `path.relative` to compute a relative path between a `SourceFile` and the one of the `rootDirs`. The problem is that the `rootDirs` get passed through `getCanonicalFileName` which lowercases the path in some platforms, while `SourceFile.fileName` is always case-insensitive. This yields a path outside of the project which we were ignoring. This change passes the `SourceFile.fileName` before passing it through `path.relative` to ensure that we get a valid result. --- .../annotations/common/src/debug_info.ts | 24 +++------------ .../src/ngtsc/annotations/common/src/util.ts | 29 +++++++++++++++++++ .../annotations/component/src/handler.ts | 5 ++-- .../ngtsc/annotations/component/src/hmr.ts | 17 +++++------ .../component/test/component_spec.ts | 4 ++- .../src/ngtsc/core/src/compiler.ts | 2 +- .../compiler-cli/test/ngtsc/ngtsc_spec.ts | 4 +-- 7 files changed, 49 insertions(+), 36 deletions(-) diff --git a/packages/compiler-cli/src/ngtsc/annotations/common/src/debug_info.ts b/packages/compiler-cli/src/ngtsc/annotations/common/src/debug_info.ts index d0edd1a73ace..3da7dab668d7 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/common/src/debug_info.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/common/src/debug_info.ts @@ -7,13 +7,15 @@ */ import {literal, R3ClassDebugInfo, WrappedNodeExpr} from '@angular/compiler'; -import * as path from 'path'; +import ts from 'typescript'; import {DeclarationNode, ReflectionHost} from '../../../reflection'; +import {getProjectRelativePath} from './util'; export function extractClassDebugInfo( clazz: DeclarationNode, reflection: ReflectionHost, + compilerHost: Pick, rootDirs: ReadonlyArray, forbidOrphanRendering: boolean, ): R3ClassDebugInfo | null { @@ -22,7 +24,7 @@ export function extractClassDebugInfo( } const srcFile = clazz.getSourceFile(); - const srcFileMaybeRelativePath = computeRelativePathIfPossible(srcFile.fileName, rootDirs); + const srcFileMaybeRelativePath = getProjectRelativePath(srcFile, rootDirs, compilerHost); return { type: new WrappedNodeExpr(clazz.name), @@ -32,21 +34,3 @@ export function extractClassDebugInfo( forbidOrphanRendering, }; } - -/** - * Computes a source file path relative to the project root folder if possible, otherwise returns - * null. - */ -function computeRelativePathIfPossible( - filePath: string, - rootDirs: ReadonlyArray, -): string | null { - for (const rootDir of rootDirs) { - const rel = path.relative(rootDir, filePath); - if (!rel.startsWith('..')) { - return rel; - } - } - - return null; -} diff --git a/packages/compiler-cli/src/ngtsc/annotations/common/src/util.ts b/packages/compiler-cli/src/ngtsc/annotations/common/src/util.ts index 533fad06ac13..ea3c3d60dadb 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/common/src/util.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/common/src/util.ts @@ -20,6 +20,7 @@ import { Statement, WrappedNodeExpr, } from '@angular/compiler'; +import {relative} from 'path'; import ts from 'typescript'; import { @@ -509,3 +510,31 @@ export function isAbstractClassDeclaration(clazz: ClassDeclaration): boolean { ? clazz.modifiers.some((mod) => mod.kind === ts.SyntaxKind.AbstractKeyword) : false; } + +/** + * Attempts to generate a project-relative path + * @param sourceFile + * @param rootDirs + * @param compilerHost + * @returns + */ +export function getProjectRelativePath( + sourceFile: ts.SourceFile, + rootDirs: readonly string[], + compilerHost: Pick, +): string | null { + // Note: we need to pass both the file name and the root directories through getCanonicalFileName, + // because the root directories might've been passed through it already while the source files + // definitely have not. This can break the relative return value, because in some platforms + // getCanonicalFileName lowercases the path. + const filePath = compilerHost.getCanonicalFileName(sourceFile.fileName); + + for (const rootDir of rootDirs) { + const rel = relative(compilerHost.getCanonicalFileName(rootDir), filePath); + if (!rel.startsWith('..')) { + return rel; + } + } + + return null; +} diff --git a/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts b/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts index 8f2a7943318b..29279becb0a0 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts @@ -221,7 +221,7 @@ export class ComponentDecoratorHandler private metaRegistry: MetadataRegistry, private metaReader: MetadataReader, private scopeReader: ComponentScopeReader, - private dtsScopeReader: DtsModuleScopeResolver, + private compilerHost: Pick, private scopeRegistry: LocalModuleScopeRegistry, private typeCheckScopeRegistry: TypeCheckScopeRegistry, private resourceRegistry: ResourceRegistry, @@ -872,11 +872,12 @@ export class ComponentDecoratorHandler classDebugInfo: extractClassDebugInfo( node, this.reflector, + this.compilerHost, this.rootDirs, /* forbidOrphanRenderering */ this.forbidOrphanRendering, ), hmrInitializerMeta: this.enableHmr - ? extractHmrInitializerMeta(node, this.reflector, this.rootDirs) + ? extractHmrInitializerMeta(node, this.reflector, this.compilerHost, this.rootDirs) : null, template, providersRequiringFactory, diff --git a/packages/compiler-cli/src/ngtsc/annotations/component/src/hmr.ts b/packages/compiler-cli/src/ngtsc/annotations/component/src/hmr.ts index 4c510ba7c156..cb5a2424e957 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/component/src/hmr.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/component/src/hmr.ts @@ -8,7 +8,8 @@ import {R3HmrInitializerMetadata, WrappedNodeExpr} from '@angular/compiler'; import {DeclarationNode, ReflectionHost} from '../../../reflection'; -import {relative} from 'path'; +import {getProjectRelativePath} from '../../common'; +import ts from 'typescript'; /** * Extracts the metadata necessary to generate an HMR initializer. @@ -16,21 +17,17 @@ import {relative} from 'path'; export function extractHmrInitializerMeta( clazz: DeclarationNode, reflection: ReflectionHost, + compilerHost: Pick, rootDirs: readonly string[], ): R3HmrInitializerMetadata | null { if (!reflection.isClass(clazz)) { return null; } - // Attempt to generate a project-relative path before falling back to the full path. - let filePath = clazz.getSourceFile().fileName; - for (const rootDir of rootDirs) { - const relativePath = relative(rootDir, filePath); - if (!relativePath.startsWith('..')) { - filePath = relativePath; - break; - } - } + const sourceFile = clazz.getSourceFile(); + const filePath = + getProjectRelativePath(sourceFile, rootDirs, compilerHost) || + compilerHost.getCanonicalFileName(sourceFile.fileName); const meta: R3HmrInitializerMetadata = { type: new WrappedNodeExpr(clazz.name), diff --git a/packages/compiler-cli/src/ngtsc/annotations/component/test/component_spec.ts b/packages/compiler-cli/src/ngtsc/annotations/component/test/component_spec.ts index 9a016e6bb471..6e940f8a3021 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/component/test/component_spec.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/component/test/component_spec.ts @@ -120,7 +120,9 @@ function setup( metaRegistry, metaReader, scopeRegistry, - dtsResolver, + { + getCanonicalFileName: (fileName) => fileName, + }, scopeRegistry, typeCheckScopeRegistry, resourceRegistry, diff --git a/packages/compiler-cli/src/ngtsc/core/src/compiler.ts b/packages/compiler-cli/src/ngtsc/core/src/compiler.ts index 765d9dc7e7fb..002d5399048b 100644 --- a/packages/compiler-cli/src/ngtsc/core/src/compiler.ts +++ b/packages/compiler-cli/src/ngtsc/core/src/compiler.ts @@ -1429,7 +1429,7 @@ export class NgCompiler { metaRegistry, metaReader, scopeReader, - depScopeReader, + this.adapter, ngModuleScopeRegistry, typeCheckScopeRegistry, resourceRegistry, diff --git a/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts b/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts index f2646f8c538f..c6e88f153d3e 100644 --- a/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts +++ b/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts @@ -10574,10 +10574,10 @@ runInEachFileSystem((os: string) => { // We need a regex match here, because the file path changes based on // the file system and the timestamp will be different for each test run. expect(jsContents).toMatch( - /import\.meta\.hot && import\.meta\.hot\.on\("angular:component-update", d => { if \(d\.id == ".*test\.ts%40Cmp"\) {/, + /import\.meta\.hot && import\.meta\.hot\.on\("angular:component-update", d => { if \(d\.id == "test\.ts%40Cmp"\) {/, ); expect(jsContents).toMatch( - /import\("\/@ng\/component\?c=.*test\.ts%40Cmp&t=\d+"\).then\(m => i0\.ɵɵreplaceMetadata\(Cmp, m\.default\)\);/, + /import\("\/@ng\/component\?c=test\.ts%40Cmp&t=\d+"\).then\(m => i0\.ɵɵreplaceMetadata\(Cmp, m\.default\)\);/, ); }); });