Skip to content

Commit ce3b664

Browse files
crisbetothePunderWoman
authored andcommitted
fix(compiler-cli): account for more expression types when determining HMR dependencies (#59323)
During the HMR dependency analysis we need to check if an identifier is top-level or not. We do this by looking at each identifier and its parent, however we didn't account for some cases. These changes expand our logic to cover more of the common node types. Related to #59310 (comment). PR Close #59323
1 parent ceadd28 commit ce3b664

File tree

2 files changed

+67
-4
lines changed

2 files changed

+67
-4
lines changed

packages/compiler-cli/src/ngtsc/hmr/src/extract_dependencies.ts

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,24 @@ class PotentialTopLevelReadsVisitor extends o.RecursiveAstVisitor {
209209
return parent.expression === node || parent.arguments.includes(node);
210210
}
211211

212-
// Identifier used in a property read is only top-level if it's the expression.
213-
if (ts.isPropertyAccessExpression(parent)) {
212+
// Identifier used in a nested expression is only top-level if it's the actual expression.
213+
if (
214+
ts.isPropertyAccessExpression(parent) ||
215+
ts.isComputedPropertyName(parent) ||
216+
ts.isTemplateSpan(parent) ||
217+
ts.isSpreadAssignment(parent) ||
218+
ts.isSpreadElement(parent) ||
219+
ts.isAwaitExpression(parent) ||
220+
ts.isNonNullExpression(parent) ||
221+
ts.isIfStatement(parent) ||
222+
ts.isDoStatement(parent) ||
223+
ts.isWhileStatement(parent) ||
224+
ts.isForInStatement(parent) ||
225+
ts.isForOfStatement(parent) ||
226+
ts.isSwitchStatement(parent) ||
227+
ts.isCaseClause(parent) ||
228+
ts.isThrowStatement(parent)
229+
) {
214230
return parent.expression === node;
215231
}
216232

@@ -224,11 +240,31 @@ class PotentialTopLevelReadsVisitor extends o.RecursiveAstVisitor {
224240
return parent.initializer === node;
225241
}
226242

227-
// Identifier in a class is only top level if it's the name.
228-
if (ts.isClassDeclaration(parent)) {
243+
// Identifier in a declaration is only top level if it's the name.
244+
// In shorthand assignments the name is also the value.
245+
if (
246+
ts.isClassDeclaration(parent) ||
247+
ts.isFunctionDeclaration(parent) ||
248+
ts.isVariableDeclaration(parent) ||
249+
ts.isShorthandPropertyAssignment(parent)
250+
) {
229251
return parent.name === node;
230252
}
231253

254+
if (ts.isElementAccessExpression(parent)) {
255+
return parent.expression === node || parent.argumentExpression === node;
256+
}
257+
258+
if (ts.isBinaryExpression(parent)) {
259+
return parent.left === node || parent.right === node;
260+
}
261+
262+
// It's unlikely that we'll run into imports/exports in this use case.
263+
// We handle them since it's simple and for completeness' sake.
264+
if (ts.isImportSpecifier(parent) || ts.isExportSpecifier(parent)) {
265+
return (parent.propertyName || parent.name) === node;
266+
}
267+
232268
// Otherwise it's not top-level.
233269
return false;
234270
}

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,5 +349,32 @@ runInEachFileSystem(() => {
349349
const hmrContents = env.driveHmr('test.ts', 'Foo');
350350
expect(hmrContents).toBe(null);
351351
});
352+
353+
it('should capture shorthand property assignment dependencies', () => {
354+
enableHmr();
355+
env.write(
356+
'test.ts',
357+
`
358+
import {Component} from '@angular/core';
359+
360+
const providers: any[] = [];
361+
362+
@Component({template: '', providers})
363+
export class Cmp {}
364+
`,
365+
);
366+
367+
env.driveMain();
368+
369+
const jsContents = env.getContents('test.js');
370+
const hmrContents = env.driveHmr('test.ts', 'Cmp');
371+
372+
expect(jsContents).toContain(
373+
'ɵɵreplaceMetadata(Cmp, m.default, [i0], [providers, Component]));',
374+
);
375+
expect(hmrContents).toContain(
376+
'export default function Cmp_UpdateMetadata(Cmp, ɵɵnamespaces, providers, Component) {',
377+
);
378+
});
352379
});
353380
});

0 commit comments

Comments
 (0)