fix(ngcc): libraries using spread in object literals cannot be processed (#34661)
Consider a library that uses a shared constant for host bindings. e.g. ```ts export const BASE_BINDINGS= { '[class.mat-themed]': '_isThemed', } ---- @Directive({ host: {...BASE_BINDINGS, '(click)': '...'} }) export class Dir1 {} @Directive({ host: {...BASE_BINDINGS, '(click)': '...'} }) export class Dir2 {} ``` Previously when these components were shipped as part of the library to NPM, consumers were able to consume `Dir1` and `Dir2`. No errors showed up. Now with Ivy, when ngcc tries to process the library, an error will be thrown. The error is stating that the host bindings should be an object (which they obviously are). This happens because TypeScript transforms the object spread to individual `Object.assign` calls (for compatibility). The partial evaluator used by the `@Directive` annotation handler is unable to process this expression because there is no integrated support for `Object.assign`. In View Engine, this was not a problem because the `metadata.json` files from the library were used to compute the host bindings. Fixes #34659 PR Close #34661
This commit is contained in:

committed by
Andrew Kushnir

parent
93ffc67bfb
commit
6b468f9b2e
@ -332,6 +332,10 @@ export interface FunctionDefinition {
|
||||
* Possible functions from TypeScript's helper library.
|
||||
*/
|
||||
export enum TsHelperFn {
|
||||
/**
|
||||
* Indicates the `__assign` function.
|
||||
*/
|
||||
Assign,
|
||||
/**
|
||||
* Indicates the `__spread` function.
|
||||
*/
|
||||
@ -342,6 +346,16 @@ export enum TsHelperFn {
|
||||
SpreadArrays,
|
||||
}
|
||||
|
||||
/**
|
||||
* Possible declarations which are known.
|
||||
*/
|
||||
export enum KnownDeclaration {
|
||||
/**
|
||||
* Indicates the JavaScript global `Object` class.
|
||||
*/
|
||||
JsGlobalObject,
|
||||
}
|
||||
|
||||
/**
|
||||
* A parameter to a function or method.
|
||||
*/
|
||||
@ -395,6 +409,11 @@ export interface BaseDeclaration<T extends ts.Declaration = ts.Declaration> {
|
||||
* TypeScript reference to the declaration itself, if one exists.
|
||||
*/
|
||||
node: T|null;
|
||||
|
||||
/**
|
||||
* If set, describes the type of the known declaration this declaration resolves to.
|
||||
*/
|
||||
known: KnownDeclaration|null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -308,12 +308,12 @@ export class TypeScriptReflectionHost implements ReflectionHost {
|
||||
if (symbol.valueDeclaration !== undefined) {
|
||||
return {
|
||||
node: symbol.valueDeclaration,
|
||||
viaModule,
|
||||
known: null, viaModule,
|
||||
};
|
||||
} else if (symbol.declarations !== undefined && symbol.declarations.length > 0) {
|
||||
return {
|
||||
node: symbol.declarations[0],
|
||||
viaModule,
|
||||
known: null, viaModule,
|
||||
};
|
||||
} else {
|
||||
return null;
|
||||
|
@ -362,6 +362,7 @@ runInEachFileSystem(() => {
|
||||
const decl = host.getDeclarationOfIdentifier(Target);
|
||||
expect(decl).toEqual({
|
||||
node: targetDecl,
|
||||
known: null,
|
||||
viaModule: 'absolute',
|
||||
});
|
||||
});
|
||||
@ -391,6 +392,7 @@ runInEachFileSystem(() => {
|
||||
const decl = host.getDeclarationOfIdentifier(Target);
|
||||
expect(decl).toEqual({
|
||||
node: targetDecl,
|
||||
known: null,
|
||||
viaModule: 'absolute',
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user