Skip to content

Commit 8744c9a

Browse files
crisbetoatscott
authored andcommitted
fix(compiler-cli): ensure HMR works with different output module type (angular#60797)
Currently when we transpile the HMR update module, we use the project's compiler options verbatim. This appears to break down with some module types, whereas we have to use a native export. These changes override the compiler options to ensure that the user's options don't end up breaking HMR. Fixes angular#60795. PR Close angular#60797
1 parent 0b69b61 commit 8744c9a

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

packages/compiler-cli/src/ngtsc/core/src/compiler.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -966,7 +966,15 @@ export class NgCompiler {
966966
const nodeText = printer.printNode(ts.EmitHint.Unspecified, callback, sourceFile);
967967

968968
return ts.transpileModule(nodeText, {
969-
compilerOptions: this.options,
969+
compilerOptions: {
970+
...this.options,
971+
972+
// Some module types can produce additional code (see #60795) whereas we need the
973+
// HMR update module to use a native `export`. Override the `target` and `module`
974+
// to ensure that it looks as expected.
975+
module: ts.ModuleKind.ES2022,
976+
target: ts.ScriptTarget.ES2022,
977+
} as ts.CompilerOptions,
970978
fileName: sourceFile.fileName,
971979
reportDiagnostics: false,
972980
}).outputText;

packages/compiler-cli/test/ngtsc/hmr_spec.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,18 @@ runInEachFileSystem(() => {
2424
env.tsconfig();
2525
});
2626

27-
function enableHmr(additionalOptions: Record<string, unknown> = {}): void {
27+
function enableHmr(
28+
additionalAngularOptions: Record<string, unknown> = {},
29+
additionalCompilerOptions: Record<string, unknown> = {},
30+
): void {
2831
env.write(
2932
'tsconfig.json',
3033
JSON.stringify({
3134
extends: './tsconfig-base.json',
35+
...additionalCompilerOptions,
3236
angularCompilerOptions: {
3337
_enableHmr: true,
34-
...additionalOptions,
38+
...additionalAngularOptions,
3539
},
3640
}),
3741
);
@@ -973,5 +977,31 @@ runInEachFileSystem(() => {
973977
expect(jsContents).toContain('newProp = 123');
974978
expect(hmrContents).toContain('export default function Cmp_UpdateMetadata');
975979
});
980+
981+
it('should generate an HMR initializer and update function for a class that depends on multiple namespaces', () => {
982+
enableHmr(undefined, {
983+
compilerOptions: {
984+
module: 'NodeNext',
985+
moduleResolution: 'NodeNext',
986+
},
987+
});
988+
989+
env.write(
990+
'test.ts',
991+
`
992+
import {Component} from '@angular/core';
993+
994+
@Component({selector: 'cmp', template: ''})
995+
export class Cmp {}
996+
`,
997+
);
998+
999+
env.driveMain();
1000+
1001+
const hmrContents = env.driveHmr('test.ts', 'Cmp');
1002+
expect(hmrContents).toContain(
1003+
'export default function Cmp_UpdateMetadata(Cmp, ɵɵnamespaces, Component) {',
1004+
);
1005+
});
9761006
});
9771007
});

0 commit comments

Comments
 (0)