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
This commit is contained in:
parent
93f07aee6c
commit
ca25c957bf
|
@ -32,7 +32,7 @@ export class DelegatingReflectionHost implements NgccReflectionHost {
|
|||
|
||||
getDeclarationOfIdentifier(id: ts.Identifier): Declaration|null {
|
||||
if (isFromDtsFile(id)) {
|
||||
return this.tsHost.getDeclarationOfIdentifier(id);
|
||||
return this.detectKnownDeclaration(this.tsHost.getDeclarationOfIdentifier(id));
|
||||
}
|
||||
return this.ngccHost.getDeclarationOfIdentifier(id);
|
||||
}
|
||||
|
@ -60,7 +60,13 @@ export class DelegatingReflectionHost implements NgccReflectionHost {
|
|||
|
||||
getExportsOfModule(module: ts.Node): Map<string, Declaration>|null {
|
||||
if (isFromDtsFile(module)) {
|
||||
return this.tsHost.getExportsOfModule(module);
|
||||
const exportMap = this.tsHost.getExportsOfModule(module);
|
||||
|
||||
if (exportMap !== null) {
|
||||
exportMap.forEach(decl => this.detectKnownDeclaration(decl));
|
||||
}
|
||||
|
||||
return exportMap;
|
||||
}
|
||||
return this.ngccHost.getExportsOfModule(module);
|
||||
}
|
||||
|
@ -154,4 +160,11 @@ export class DelegatingReflectionHost implements NgccReflectionHost {
|
|||
getEndOfClass(classSymbol: NgccClassSymbol): ts.Node {
|
||||
return this.ngccHost.getEndOfClass(classSymbol);
|
||||
}
|
||||
|
||||
detectKnownDeclaration(decl: null): null;
|
||||
detectKnownDeclaration<T extends Declaration>(decl: T): T;
|
||||
detectKnownDeclaration<T extends Declaration>(decl: T|null): T|null;
|
||||
detectKnownDeclaration<T extends Declaration>(decl: T|null): T|null {
|
||||
return this.ngccHost.detectKnownDeclaration(decl);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
*/
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {ClassDeclaration, ConcreteDeclaration, Decorator, ReflectionHost} from '../../../src/ngtsc/reflection';
|
||||
import {ClassDeclaration, ConcreteDeclaration, Declaration, Decorator, ReflectionHost} from '../../../src/ngtsc/reflection';
|
||||
|
||||
export const PRE_R3_MARKER = '__PRE_R3__';
|
||||
export const POST_R3_MARKER = '__POST_R3__';
|
||||
|
||||
export type SwitchableVariableDeclaration = ts.VariableDeclaration & {initializer: ts.Identifier};
|
||||
export type SwitchableVariableDeclaration = ts.VariableDeclaration&{initializer: ts.Identifier};
|
||||
export function isSwitchableVariableDeclaration(node: ts.Node):
|
||||
node is SwitchableVariableDeclaration {
|
||||
return ts.isVariableDeclaration(node) && !!node.initializer &&
|
||||
|
@ -47,7 +47,7 @@ export interface ModuleWithProvidersFunction {
|
|||
* The symbol corresponding to a "class" declaration. I.e. a `ts.Symbol` whose `valueDeclaration` is
|
||||
* a `ClassDeclaration`.
|
||||
*/
|
||||
export type ClassSymbol = ts.Symbol & {valueDeclaration: ClassDeclaration};
|
||||
export type ClassSymbol = ts.Symbol&{valueDeclaration: ClassDeclaration};
|
||||
|
||||
/**
|
||||
* 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 {
|
|||
* @param classSymbol The class whose statements we want.
|
||||
*/
|
||||
getEndOfClass(classSymbol: NgccClassSymbol): ts.Node;
|
||||
|
||||
/**
|
||||
* Check whether a `Declaration` corresponds with a known declaration and set its `known` property
|
||||
* to the appropriate `KnownDeclaration`.
|
||||
*
|
||||
* @param decl The `Declaration` to check or `null` if there is no declaration.
|
||||
* @return The passed in `Declaration` (potentially enhanced with a `KnownDeclaration`).
|
||||
*/
|
||||
detectKnownDeclaration<T extends Declaration>(decl: T|null): T|null;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue