feat(ivy): accept multiple values for exportAs in the compiler (#28001)
exportAs in @Directive metadata supports multiple values, separated by commas. Previously it was treated as a single value string. This commit modifies the compiler to understand that exportAs is a string[]. It stops short of carrying the multiple values through to the runtime. Instead, it only emits the first one. A future commit will modify the runtime to accept all the values. PR Close #28001
This commit is contained in:
parent
6003145422
commit
142553abc6
|
@ -177,7 +177,7 @@ export function extractDirectiveMetadata(
|
||||||
member.name === 'ngOnChanges');
|
member.name === 'ngOnChanges');
|
||||||
|
|
||||||
// Parse exportAs.
|
// Parse exportAs.
|
||||||
let exportAs: string|null = null;
|
let exportAs: string[]|null = null;
|
||||||
if (directive.has('exportAs')) {
|
if (directive.has('exportAs')) {
|
||||||
const expr = directive.get('exportAs') !;
|
const expr = directive.get('exportAs') !;
|
||||||
const resolved = evaluator.evaluate(expr);
|
const resolved = evaluator.evaluate(expr);
|
||||||
|
@ -185,7 +185,7 @@ export function extractDirectiveMetadata(
|
||||||
throw new FatalDiagnosticError(
|
throw new FatalDiagnosticError(
|
||||||
ErrorCode.VALUE_HAS_WRONG_TYPE, expr, `exportAs must be a string`);
|
ErrorCode.VALUE_HAS_WRONG_TYPE, expr, `exportAs must be a string`);
|
||||||
}
|
}
|
||||||
exportAs = resolved;
|
exportAs = resolved.split(',').map(part => part.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detect if the component inherits from another class
|
// Detect if the component inherits from another class
|
||||||
|
|
|
@ -366,7 +366,7 @@ export class SelectorScopeRegistry {
|
||||||
name: clazz.name !.text,
|
name: clazz.name !.text,
|
||||||
directive: ref,
|
directive: ref,
|
||||||
isComponent: def.name === 'ngComponentDef', selector,
|
isComponent: def.name === 'ngComponentDef', selector,
|
||||||
exportAs: readStringType(def.type.typeArguments[2]),
|
exportAs: readStringArrayType(def.type.typeArguments[2]),
|
||||||
inputs: readStringMapType(def.type.typeArguments[3]),
|
inputs: readStringMapType(def.type.typeArguments[3]),
|
||||||
outputs: readStringMapType(def.type.typeArguments[4]),
|
outputs: readStringMapType(def.type.typeArguments[4]),
|
||||||
queries: readStringArrayType(def.type.typeArguments[5]),
|
queries: readStringArrayType(def.type.typeArguments[5]),
|
||||||
|
|
|
@ -119,7 +119,7 @@ export interface R3DirectiveMetadataFacade {
|
||||||
inputs: string[];
|
inputs: string[];
|
||||||
outputs: string[];
|
outputs: string[];
|
||||||
usesInheritance: boolean;
|
usesInheritance: boolean;
|
||||||
exportAs: string|null;
|
exportAs: string[]|null;
|
||||||
providers: Provider[]|null;
|
providers: Provider[]|null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ export interface R3DirectiveMetadata {
|
||||||
* Reference name under which to export the directive's type in a template,
|
* Reference name under which to export the directive's type in a template,
|
||||||
* if any.
|
* if any.
|
||||||
*/
|
*/
|
||||||
exportAs: string|null;
|
exportAs: string[]|null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of providers defined in the directive.
|
* The list of providers defined in the directive.
|
||||||
|
|
|
@ -117,7 +117,9 @@ function baseDirectiveFields(
|
||||||
definitionMap.set('outputs', conditionallyCreateMapObjectLiteral(meta.outputs));
|
definitionMap.set('outputs', conditionallyCreateMapObjectLiteral(meta.outputs));
|
||||||
|
|
||||||
if (meta.exportAs !== null) {
|
if (meta.exportAs !== null) {
|
||||||
definitionMap.set('exportAs', o.literal(meta.exportAs));
|
// TODO: handle multiple exportAs values (currently only the first is taken).
|
||||||
|
const [exportAs] = meta.exportAs;
|
||||||
|
definitionMap.set('exportAs', o.literal(exportAs));
|
||||||
}
|
}
|
||||||
|
|
||||||
return {definitionMap, statements: result.statements};
|
return {definitionMap, statements: result.statements};
|
||||||
|
@ -605,7 +607,8 @@ function createTypeForDef(meta: R3DirectiveMetadata, typeBase: o.ExternalReferen
|
||||||
return o.expressionType(o.importExpr(typeBase, [
|
return o.expressionType(o.importExpr(typeBase, [
|
||||||
typeWithParameters(meta.type, meta.typeArgumentCount),
|
typeWithParameters(meta.type, meta.typeArgumentCount),
|
||||||
stringAsType(selectorForType),
|
stringAsType(selectorForType),
|
||||||
meta.exportAs !== null ? stringAsType(meta.exportAs) : o.NONE_TYPE,
|
// TODO: handle multiple exportAs values (currently only the first is taken).
|
||||||
|
meta.exportAs !== null ? stringArrayAsType(meta.exportAs) : o.NONE_TYPE,
|
||||||
stringMapAsType(meta.inputs),
|
stringMapAsType(meta.inputs),
|
||||||
stringMapAsType(meta.outputs),
|
stringMapAsType(meta.outputs),
|
||||||
stringArrayAsType(meta.queries.map(q => q.propertyName)),
|
stringArrayAsType(meta.queries.map(q => q.propertyName)),
|
||||||
|
|
|
@ -58,7 +58,7 @@ export interface DirectiveMeta {
|
||||||
*
|
*
|
||||||
* Null otherwise
|
* Null otherwise
|
||||||
*/
|
*/
|
||||||
exportAs: string|null;
|
exportAs: string[]|null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -259,7 +259,10 @@ class DirectiveBinder<DirectiveT extends DirectiveMeta> implements Visitor {
|
||||||
dirTarget = directives.find(dir => dir.isComponent) || null;
|
dirTarget = directives.find(dir => dir.isComponent) || null;
|
||||||
} else {
|
} else {
|
||||||
// This is a reference to a directive exported via exportAs. One should exist.
|
// This is a reference to a directive exported via exportAs. One should exist.
|
||||||
dirTarget = directives.find(dir => dir.exportAs === ref.value) || null;
|
dirTarget =
|
||||||
|
directives.find(
|
||||||
|
dir => dir.exportAs !== null && dir.exportAs.some(value => value === ref.value)) ||
|
||||||
|
null;
|
||||||
|
|
||||||
// Check if a matching directive was found, and error if it wasn't.
|
// Check if a matching directive was found, and error if it wasn't.
|
||||||
if (dirTarget === null) {
|
if (dirTarget === null) {
|
||||||
|
|
|
@ -60,7 +60,7 @@ export const enum DirectiveDefFlags {ContentQuery = 0b10}
|
||||||
export interface PipeType<T> extends Type<T> { ngPipeDef: never; }
|
export interface PipeType<T> extends Type<T> { ngPipeDef: never; }
|
||||||
|
|
||||||
export type DirectiveDefWithMeta<
|
export type DirectiveDefWithMeta<
|
||||||
T, Selector extends string, ExportAs extends string, InputMap extends{[key: string]: string},
|
T, Selector extends string, ExportAs extends string[], InputMap extends{[key: string]: string},
|
||||||
OutputMap extends{[key: string]: string}, QueryFields extends string[]> = DirectiveDef<T>;
|
OutputMap extends{[key: string]: string}, QueryFields extends string[]> = DirectiveDef<T>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -163,7 +163,7 @@ export interface DirectiveDef<T> extends BaseDef<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ComponentDefWithMeta<
|
export type ComponentDefWithMeta<
|
||||||
T, Selector extends String, ExportAs extends string, InputMap extends{[key: string]: string},
|
T, Selector extends String, ExportAs extends string[], InputMap extends{[key: string]: string},
|
||||||
OutputMap extends{[key: string]: string}, QueryFields extends string[]> = ComponentDef<T>;
|
OutputMap extends{[key: string]: string}, QueryFields extends string[]> = ComponentDef<T>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -119,7 +119,7 @@ export interface R3DirectiveMetadataFacade {
|
||||||
inputs: string[];
|
inputs: string[];
|
||||||
outputs: string[];
|
outputs: string[];
|
||||||
usesInheritance: boolean;
|
usesInheritance: boolean;
|
||||||
exportAs: string|null;
|
exportAs: string[]|null;
|
||||||
providers: Provider[]|null;
|
providers: Provider[]|null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,7 @@ function directiveMetadata(type: Type<any>, metadata: Directive): R3DirectiveMet
|
||||||
},
|
},
|
||||||
typeSourceSpan: null !,
|
typeSourceSpan: null !,
|
||||||
usesInheritance: !extendsDirectlyFromObject(type),
|
usesInheritance: !extendsDirectlyFromObject(type),
|
||||||
exportAs: metadata.exportAs || null,
|
exportAs: extractExportAs(metadata.exportAs),
|
||||||
providers: metadata.providers || null,
|
providers: metadata.providers || null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -189,6 +189,14 @@ function extractQueriesMetadata(
|
||||||
return queriesMeta;
|
return queriesMeta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function extractExportAs(exportAs: string | undefined): string[]|null {
|
||||||
|
if (exportAs === undefined) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return exportAs.split(',').map(part => part.trim());
|
||||||
|
}
|
||||||
|
|
||||||
function isContentQuery(value: any): value is Query {
|
function isContentQuery(value: any): value is Query {
|
||||||
const name = value.ngMetadataName;
|
const name = value.ngMetadataName;
|
||||||
return name === 'ContentChild' || name === 'ContentChildren';
|
return name === 'ContentChild' || name === 'ContentChildren';
|
||||||
|
|
Loading…
Reference in New Issue