fix(ivy): ngcc generates setClassMetadata calls for ES5 bundles (#27438)
ngcc would feed ngtsc with the function declaration inside of an IIFE as that is considered the class symbol's declaration node, according to TypeScript's `ts.Symbol.valueDeclaration`. ngtsc however only considered variable decls and actual class decls as potential class declarations, so given the function declaration node it would fail to generate the `setClassMetadata` call. ngtsc no longer makes its own assumptions about what classes look like, but always asks the reflection host to yield this kind of information. PR Close #27438
This commit is contained in:
parent
84084b1bdb
commit
52544ffaa3
|
@ -38,7 +38,9 @@ export class Esm5ReflectionHost extends Esm2015ReflectionHost {
|
|||
/**
|
||||
* Check whether the given node actually represents a class.
|
||||
*/
|
||||
isClass(node: ts.Node): boolean { return super.isClass(node) || !!this.getClassSymbol(node); }
|
||||
isClass(node: ts.Node): node is ts.NamedDeclaration {
|
||||
return super.isClass(node) || !!this.getClassSymbol(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a symbol for a node that we think is a class.
|
||||
|
|
|
@ -20,10 +20,7 @@ import {CtorParameter, Decorator, ReflectionHost} from '../../host';
|
|||
*/
|
||||
export function generateSetClassMetadataCall(
|
||||
clazz: ts.Declaration, reflection: ReflectionHost, isCore: boolean): Statement|null {
|
||||
// Classes come in two flavors, class declarations (ES2015) and variable declarations (ES5).
|
||||
// Both must have a declared name to have metadata set on them.
|
||||
if ((!ts.isClassDeclaration(clazz) && !ts.isVariableDeclaration(clazz)) ||
|
||||
clazz.name === undefined || !ts.isIdentifier(clazz.name)) {
|
||||
if (!reflection.isClass(clazz) || clazz.name === undefined || !ts.isIdentifier(clazz.name)) {
|
||||
return null;
|
||||
}
|
||||
const id = ts.updateIdentifier(clazz.name);
|
||||
|
|
|
@ -423,7 +423,7 @@ export interface ReflectionHost {
|
|||
/**
|
||||
* Check whether the given node actually represents a class.
|
||||
*/
|
||||
isClass(node: ts.Node): boolean;
|
||||
isClass(node: ts.Node): node is ts.NamedDeclaration;
|
||||
|
||||
hasBaseClass(node: ts.Declaration): boolean;
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ export class TypeScriptReflectionHost implements ReflectionHost {
|
|||
return map;
|
||||
}
|
||||
|
||||
isClass(node: ts.Node): boolean {
|
||||
isClass(node: ts.Node): node is ts.NamedDeclaration {
|
||||
// In TypeScript code, classes are ts.ClassDeclarations.
|
||||
return ts.isClassDeclaration(node);
|
||||
}
|
||||
|
|
|
@ -353,7 +353,7 @@ class StaticInterpreter {
|
|||
return this.visitExpression(node.expression, context);
|
||||
} else if (ts.isNonNullExpression(node)) {
|
||||
return this.visitExpression(node.expression, context);
|
||||
} else if (isPossibleClassDeclaration(node) && this.host.isClass(node)) {
|
||||
} else if (this.host.isClass(node)) {
|
||||
return this.visitDeclaration(node, context);
|
||||
} else {
|
||||
return DYNAMIC_VALUE;
|
||||
|
@ -565,7 +565,7 @@ class StaticInterpreter {
|
|||
return lhs[rhs];
|
||||
} else if (lhs instanceof Reference) {
|
||||
const ref = lhs.node;
|
||||
if (isPossibleClassDeclaration(ref) && this.host.isClass(ref)) {
|
||||
if (this.host.isClass(ref)) {
|
||||
let absoluteModuleName = context.absoluteModuleName;
|
||||
if (lhs instanceof NodeReference || lhs instanceof AbsoluteReference) {
|
||||
absoluteModuleName = lhs.moduleName || absoluteModuleName;
|
||||
|
@ -761,10 +761,6 @@ function identifierOfDeclaration(decl: ts.Declaration): ts.Identifier|undefined
|
|||
}
|
||||
}
|
||||
|
||||
function isPossibleClassDeclaration(node: ts.Node): node is ts.Declaration {
|
||||
return ts.isClassDeclaration(node) || ts.isVariableDeclaration(node);
|
||||
}
|
||||
|
||||
function isVariableDeclarationDeclared(node: ts.VariableDeclaration): boolean {
|
||||
if (node.parent === undefined || !ts.isVariableDeclarationList(node.parent)) {
|
||||
return false;
|
||||
|
|
Loading…
Reference in New Issue