fix(compiler-cli): preserve defer block dependencies during HMR when class metadata is disabled by crisbeto · Pull Request #59313 · angular/angular · GitHub
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions packages/compiler-cli/src/ngtsc/hmr/src/extract_dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@
* found in the LICENSE file at https://angular.dev/license
*/

import {R3CompiledExpression, R3HmrNamespaceDependency, outputAst as o} from '@angular/compiler';
import {
DeferBlockDepsEmitMode,
R3CompiledExpression,
R3ComponentDeferMetadata,
R3HmrNamespaceDependency,
outputAst as o,
} from '@angular/compiler';
import {DeclarationNode} from '../../reflection';
import {CompileResult} from '../../transform';
import ts from 'typescript';
Expand All @@ -16,21 +22,23 @@ import ts from 'typescript';
* @param sourceFile File in which the file is being compiled.
* @param definition Compiled component definition.
* @param factory Compiled component factory.
* @param deferBlockMetadata Metadata about the defer blocks in the component.
* @param classMetadata Compiled `setClassMetadata` expression, if any.
* @param debugInfo Compiled `setClassDebugInfo` expression, if any.
*/
export function extractHmrDependencies(
node: DeclarationNode,
definition: R3CompiledExpression,
factory: CompileResult,
deferBlockMetadata: R3ComponentDeferMetadata,
classMetadata: o.Statement | null,
debugInfo: o.Statement | null,
): {local: string[]; external: R3HmrNamespaceDependency[]} {
const name = ts.isClassDeclaration(node) && node.name ? node.name.text : null;
const visitor = new PotentialTopLevelReadsVisitor();
const sourceFile = node.getSourceFile();

// Visit all of the compiled expression to look for potential
// Visit all of the compiled expressions to look for potential
// local references that would have to be retained.
definition.expression.visitExpression(visitor, null);
definition.statements.forEach((statement) => statement.visitStatement(visitor, null));
Expand All @@ -39,6 +47,12 @@ export function extractHmrDependencies(
classMetadata?.visitStatement(visitor, null);
debugInfo?.visitStatement(visitor, null);

if (deferBlockMetadata.mode === DeferBlockDepsEmitMode.PerBlock) {
deferBlockMetadata.blocks.forEach((loader) => loader?.visitExpression(visitor, null));
} else {
deferBlockMetadata.dependenciesFn?.visitExpression(visitor, null);
}

// Filter out only the references to defined top-level symbols. This allows us to ignore local
// variables inside of functions. Note that we filter out the class name since it is always
// defined and it saves us having to repeat this logic wherever the locals are consumed.
Expand Down
18 changes: 16 additions & 2 deletions packages/compiler-cli/src/ngtsc/hmr/src/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@
* found in the LICENSE file at https://angular.dev/license
*/

import {R3CompiledExpression, R3HmrMetadata, outputAst as o} from '@angular/compiler';
import {
R3CompiledExpression,
R3ComponentDeferMetadata,
R3HmrMetadata,
outputAst as o,
} from '@angular/compiler';
import {DeclarationNode, ReflectionHost} from '../../reflection';
import {getProjectRelativePath} from '../../util/src/path';
import {CompileResult} from '../../transform';
Expand All @@ -21,6 +26,7 @@ import ts from 'typescript';
* @param rootDirs Root directories configured by the user.
* @param definition Analyzed component definition.
* @param factory Analyzed component factory.
* @param deferBlockMetadata Metadata about the defer blocks in the component.
* @param classMetadata Analyzed `setClassMetadata` expression, if any.
* @param debugInfo Analyzed `setClassDebugInfo` expression, if any.
*/
Expand All @@ -31,6 +37,7 @@ export function extractHmrMetatadata(
rootDirs: readonly string[],
definition: R3CompiledExpression,
factory: CompileResult,
deferBlockMetadata: R3ComponentDeferMetadata,
classMetadata: o.Statement | null,
debugInfo: o.Statement | null,
): R3HmrMetadata | null {
Expand All @@ -43,7 +50,14 @@ export function extractHmrMetatadata(
getProjectRelativePath(sourceFile.fileName, rootDirs, compilerHost) ||
compilerHost.getCanonicalFileName(sourceFile.fileName);

const dependencies = extractHmrDependencies(clazz, definition, factory, classMetadata, debugInfo);
const dependencies = extractHmrDependencies(
clazz,
definition,
factory,
deferBlockMetadata,
classMetadata,
debugInfo,
);
const meta: R3HmrMetadata = {
type: new o.WrappedNodeExpr(clazz.name),
className: clazz.name.text,
Expand Down
57 changes: 56 additions & 1 deletion packages/compiler-cli/test/ngtsc/hmr_spec.ts