Skip to content

Commit ca25c95

Browse files
gkalpakkara
authored andcommitted
fix(ngcc): correctly detect imported TypeScript helpers (#36284)
The `NgccReflectionHost`s have logic for detecting certain known declarations (such as `Object.assign()` and TypeScript helpers), which allows the `PartialEvaluator` to evaluate expressions it would not be able to statically evaluate otherwise. In #36089, `DelegatingReflectionHost` was introduced, which delegates to a TypeScript `ReflectionHost` when reflecting on TypeScript files, which for ngcc's case means `.d.ts` files of dependencies. As a result, ngcc lost the ability to detect TypeScript helpers imported from `tslib`, because `DelegatingReflectionHost` was not able to apply the known declaration detection logic while reflecting on `tslib`'s `.d.ts` files. This commit fixes this by ensuring `DelegatingReflectionHost` calls the `NgccReflectionHost`'s `detectKnownDeclaration()` method as necessary, even when using the TypeScript `ReflectionHost`. NOTE: The previous commit exposed a bug in ngcc that was hidden due to the tests' being inconsistent with how the `ReflectionHost`s are used in the actual program. The changes in this commit are verified by ensuring the failing tests are now passing (hence no new tests are added). PR Close #36284
1 parent 93f07ae commit ca25c95

File tree

2 files changed

+27
-5
lines changed

2 files changed

+27
-5
lines changed

packages/compiler-cli/ngcc/src/host/delegating_host.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export class DelegatingReflectionHost implements NgccReflectionHost {
3232

3333
getDeclarationOfIdentifier(id: ts.Identifier): Declaration|null {
3434
if (isFromDtsFile(id)) {
35-
return this.tsHost.getDeclarationOfIdentifier(id);
35+
return this.detectKnownDeclaration(this.tsHost.getDeclarationOfIdentifier(id));
3636
}
3737
return this.ngccHost.getDeclarationOfIdentifier(id);
3838
}
@@ -60,7 +60,13 @@ export class DelegatingReflectionHost implements NgccReflectionHost {
6060

6161
getExportsOfModule(module: ts.Node): Map<string, Declaration>|null {
6262
if (isFromDtsFile(module)) {
63-
return this.tsHost.getExportsOfModule(module);
63+
const exportMap = this.tsHost.getExportsOfModule(module);
64+
65+
if (exportMap !== null) {
66+
exportMap.forEach(decl => this.detectKnownDeclaration(decl));
67+
}
68+
69+
return exportMap;
6470
}
6571
return this.ngccHost.getExportsOfModule(module);
6672
}
@@ -154,4 +160,11 @@ export class DelegatingReflectionHost implements NgccReflectionHost {
154160
getEndOfClass(classSymbol: NgccClassSymbol): ts.Node {
155161
return this.ngccHost.getEndOfClass(classSymbol);
156162
}
163+
164+
detectKnownDeclaration(decl: null): null;
165+
detectKnownDeclaration<T extends Declaration>(decl: T): T;
166+
detectKnownDeclaration<T extends Declaration>(decl: T|null): T|null;
167+
detectKnownDeclaration<T extends Declaration>(decl: T|null): T|null {
168+
return this.ngccHost.detectKnownDeclaration(decl);
169+
}
157170
}

packages/compiler-cli/ngcc/src/host/ngcc_host.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
*/
88
import * as ts from 'typescript';
99

10-
import {ClassDeclaration, ConcreteDeclaration, Decorator, ReflectionHost} from '../../../src/ngtsc/reflection';
10+
import {ClassDeclaration, ConcreteDeclaration, Declaration, Decorator, ReflectionHost} from '../../../src/ngtsc/reflection';
1111

1212
export const PRE_R3_MARKER = '__PRE_R3__';
1313
export const POST_R3_MARKER = '__POST_R3__';
1414

15-
export type SwitchableVariableDeclaration = ts.VariableDeclaration & {initializer: ts.Identifier};
15+
export type SwitchableVariableDeclaration = ts.VariableDeclaration&{initializer: ts.Identifier};
1616
export function isSwitchableVariableDeclaration(node: ts.Node):
1717
node is SwitchableVariableDeclaration {
1818
return ts.isVariableDeclaration(node) && !!node.initializer &&
@@ -47,7 +47,7 @@ export interface ModuleWithProvidersFunction {
4747
* The symbol corresponding to a "class" declaration. I.e. a `ts.Symbol` whose `valueDeclaration` is
4848
* a `ClassDeclaration`.
4949
*/
50-
export type ClassSymbol = ts.Symbol & {valueDeclaration: ClassDeclaration};
50+
export type ClassSymbol = ts.Symbol&{valueDeclaration: ClassDeclaration};
5151

5252
/**
5353
* A representation of a class that accounts for the potential existence of two `ClassSymbol`s for a
@@ -128,4 +128,13 @@ export interface NgccReflectionHost extends ReflectionHost {
128128
* @param classSymbol The class whose statements we want.
129129
*/
130130
getEndOfClass(classSymbol: NgccClassSymbol): ts.Node;
131+
132+
/**
133+
* Check whether a `Declaration` corresponds with a known declaration and set its `known` property
134+
* to the appropriate `KnownDeclaration`.
135+
*
136+
* @param decl The `Declaration` to check or `null` if there is no declaration.
137+
* @return The passed in `Declaration` (potentially enhanced with a `KnownDeclaration`).
138+
*/
139+
detectKnownDeclaration<T extends Declaration>(decl: T|null): T|null;
131140
}

0 commit comments

Comments
 (0)