fix(ivy): queries not being inherited from undecorated classes (#30015)
Fixes view and content queries not being inherited in Ivy, if the base class hasn't been annotated with an Angular decorator (e.g. `Component` or `Directive`). Also reworks the way the `ngBaseDef` is created so that it is added at the same point as the queries, rather than inside of the `Input` and `Output` decorators. This PR partially resolves FW-1275. Support for host bindings will be added in a follow-up, because this PR is somewhat large as it is. PR Close #30015
This commit is contained in:

committed by
Andrew Kushnir

parent
8ca208ff59
commit
c7f1b0a97f
@ -37,6 +37,8 @@ export interface CompilerFacade {
|
||||
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3DirectiveMetadataFacade): any;
|
||||
compileComponent(
|
||||
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3ComponentMetadataFacade): any;
|
||||
compileBase(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3BaseMetadataFacade):
|
||||
any;
|
||||
|
||||
createParseSourceSpan(kind: string, typeName: string, sourceUrl: string): ParseSourceSpan;
|
||||
|
||||
@ -146,6 +148,13 @@ export interface R3ComponentMetadataFacade extends R3DirectiveMetadataFacade {
|
||||
changeDetection?: ChangeDetectionStrategy;
|
||||
}
|
||||
|
||||
export interface R3BaseMetadataFacade {
|
||||
inputs?: {[key: string]: string | [string, string]};
|
||||
outputs?: {[key: string]: string};
|
||||
queries?: R3QueryMetadataFacade[];
|
||||
viewQueries?: R3QueryMetadataFacade[];
|
||||
}
|
||||
|
||||
export type ViewEncapsulation = number;
|
||||
|
||||
export type ChangeDetectionStrategy = number;
|
||||
|
@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
|
||||
import {CompilerFacade, CoreEnvironment, ExportedCompilerFacade, R3ComponentMetadataFacade, R3DependencyMetadataFacade, R3DirectiveMetadataFacade, R3InjectableMetadataFacade, R3InjectorMetadataFacade, R3NgModuleMetadataFacade, R3PipeMetadataFacade, R3QueryMetadataFacade, StringMap, StringMapWithRename} from './compiler_facade_interface';
|
||||
import {CompilerFacade, CoreEnvironment, ExportedCompilerFacade, R3BaseMetadataFacade, R3ComponentMetadataFacade, R3DependencyMetadataFacade, R3DirectiveMetadataFacade, R3InjectableMetadataFacade, R3InjectorMetadataFacade, R3NgModuleMetadataFacade, R3PipeMetadataFacade, R3QueryMetadataFacade, StringMap, StringMapWithRename} from './compiler_facade_interface';
|
||||
import {ConstantPool} from './constant_pool';
|
||||
import {HostBinding, HostListener, Input, Output, Type} from './core';
|
||||
import {compileInjectable} from './injectable_compiler_2';
|
||||
@ -21,7 +21,7 @@ import {R3InjectorMetadata, R3NgModuleMetadata, compileInjector, compileNgModule
|
||||
import {compilePipeFromMetadata} from './render3/r3_pipe_compiler';
|
||||
import {R3Reference} from './render3/util';
|
||||
import {R3DirectiveMetadata, R3QueryMetadata} from './render3/view/api';
|
||||
import {ParsedHostBindings, compileComponentFromMetadata, compileDirectiveFromMetadata, parseHostBindings, verifyHostBindings} from './render3/view/compiler';
|
||||
import {ParsedHostBindings, compileBaseDefFromMetadata, compileComponentFromMetadata, compileDirectiveFromMetadata, parseHostBindings, verifyHostBindings} from './render3/view/compiler';
|
||||
import {makeBindingParser, parseTemplate} from './render3/view/template';
|
||||
import {ResourceLoader} from './resource_loader';
|
||||
import {DomElementSchemaRegistry} from './schema/dom_element_schema_registry';
|
||||
@ -151,6 +151,20 @@ export class CompilerFacadeImpl implements CompilerFacade {
|
||||
res.expression, angularCoreEnv, `ng:///${facade.name}.js`, preStatements);
|
||||
}
|
||||
|
||||
compileBase(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, facade: R3BaseMetadataFacade):
|
||||
any {
|
||||
const constantPool = new ConstantPool();
|
||||
const meta = {
|
||||
...facade,
|
||||
viewQueries: facade.viewQueries ? facade.viewQueries.map(convertToR3QueryMetadata) :
|
||||
facade.viewQueries,
|
||||
queries: facade.queries ? facade.queries.map(convertToR3QueryMetadata) : facade.queries
|
||||
};
|
||||
const res = compileBaseDefFromMetadata(meta, constantPool);
|
||||
return this.jitExpression(
|
||||
res.expression, angularCoreEnv, sourceMapUrl, constantPool.statements);
|
||||
}
|
||||
|
||||
createParseSourceSpan(kind: string, typeName: string, sourceUrl: string): ParseSourceSpan {
|
||||
return r3JitTypeSourceSpan(kind, typeName, sourceUrl);
|
||||
}
|
||||
|
@ -66,11 +66,13 @@ function baseDirectiveFields(
|
||||
|
||||
if (meta.queries.length > 0) {
|
||||
// e.g. `contentQueries: (rf, ctx, dirIndex) => { ... }
|
||||
definitionMap.set('contentQueries', createContentQueriesFunction(meta, constantPool));
|
||||
definitionMap.set(
|
||||
'contentQueries', createContentQueriesFunction(meta.queries, constantPool, meta.name));
|
||||
}
|
||||
|
||||
if (meta.viewQueries.length) {
|
||||
definitionMap.set('viewQuery', createViewQueriesFunction(meta, constantPool));
|
||||
definitionMap.set(
|
||||
'viewQuery', createViewQueriesFunction(meta.viewQueries, constantPool, meta.name));
|
||||
}
|
||||
|
||||
// Initialize hostVarsCount to number of bound host properties (interpolations illegal),
|
||||
@ -163,13 +165,15 @@ export function compileDirectiveFromMetadata(
|
||||
export interface R3BaseRefMetaData {
|
||||
inputs?: {[key: string]: string | [string, string]};
|
||||
outputs?: {[key: string]: string};
|
||||
viewQueries?: R3QueryMetadata[];
|
||||
queries?: R3QueryMetadata[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a base definition for the render3 runtime as defined by {@link R3BaseRefMetadata}
|
||||
* @param meta the metadata used for compilation.
|
||||
*/
|
||||
export function compileBaseDefFromMetadata(meta: R3BaseRefMetaData) {
|
||||
export function compileBaseDefFromMetadata(meta: R3BaseRefMetaData, constantPool: ConstantPool) {
|
||||
const definitionMap = new DefinitionMap();
|
||||
if (meta.inputs) {
|
||||
const inputs = meta.inputs;
|
||||
@ -188,9 +192,14 @@ export function compileBaseDefFromMetadata(meta: R3BaseRefMetaData) {
|
||||
});
|
||||
definitionMap.set('outputs', o.literalMap(outputsMap));
|
||||
}
|
||||
if (meta.viewQueries && meta.viewQueries.length > 0) {
|
||||
definitionMap.set('viewQuery', createViewQueriesFunction(meta.viewQueries, constantPool));
|
||||
}
|
||||
if (meta.queries && meta.queries.length > 0) {
|
||||
definitionMap.set('contentQueries', createContentQueriesFunction(meta.queries, constantPool));
|
||||
}
|
||||
|
||||
const expression = o.importExpr(R3.defineBase).callFn([definitionMap.toLiteralMap()]);
|
||||
|
||||
const type = new o.ExpressionType(o.importExpr(R3.BaseDef));
|
||||
|
||||
return {expression, type};
|
||||
@ -475,12 +484,12 @@ function convertAttributesToExpressions(attributes: {[name: string]: o.Expressio
|
||||
|
||||
// Define and update any content queries
|
||||
function createContentQueriesFunction(
|
||||
meta: R3DirectiveMetadata, constantPool: ConstantPool): o.Expression {
|
||||
queries: R3QueryMetadata[], constantPool: ConstantPool, name?: string): o.Expression {
|
||||
const createStatements: o.Statement[] = [];
|
||||
const updateStatements: o.Statement[] = [];
|
||||
const tempAllocator = temporaryAllocator(updateStatements, TEMPORARY_NAME);
|
||||
|
||||
for (const query of meta.queries) {
|
||||
for (const query of queries) {
|
||||
// creation, e.g. r3.contentQuery(dirIndex, somePredicate, true, null);
|
||||
const args = [o.variable('dirIndex'), ...prepareQueryParams(query, constantPool) as any];
|
||||
|
||||
@ -498,7 +507,7 @@ function createContentQueriesFunction(
|
||||
updateStatements.push(refresh.and(updateDirective).toStmt());
|
||||
}
|
||||
|
||||
const contentQueriesFnName = meta.name ? `${meta.name}_ContentQueries` : null;
|
||||
const contentQueriesFnName = name ? `${name}_ContentQueries` : null;
|
||||
return o.fn(
|
||||
[
|
||||
new o.FnParam(RENDER_FLAGS, o.NUMBER_TYPE), new o.FnParam(CONTEXT_NAME, null),
|
||||
@ -549,12 +558,12 @@ function createTypeForDef(meta: R3DirectiveMetadata, typeBase: o.ExternalReferen
|
||||
|
||||
// Define and update any view queries
|
||||
function createViewQueriesFunction(
|
||||
meta: R3DirectiveMetadata, constantPool: ConstantPool): o.Expression {
|
||||
viewQueries: R3QueryMetadata[], constantPool: ConstantPool, name?: string): o.Expression {
|
||||
const createStatements: o.Statement[] = [];
|
||||
const updateStatements: o.Statement[] = [];
|
||||
const tempAllocator = temporaryAllocator(updateStatements, TEMPORARY_NAME);
|
||||
|
||||
meta.viewQueries.forEach((query: R3QueryMetadata) => {
|
||||
viewQueries.forEach((query: R3QueryMetadata) => {
|
||||
const queryInstruction = query.static ? R3.staticViewQuery : R3.viewQuery;
|
||||
|
||||
// creation, e.g. r3.viewQuery(somePredicate, true);
|
||||
@ -572,7 +581,7 @@ function createViewQueriesFunction(
|
||||
updateStatements.push(refresh.and(updateDirective).toStmt());
|
||||
});
|
||||
|
||||
const viewQueryFnName = meta.name ? `${meta.name}_Query` : null;
|
||||
const viewQueryFnName = name ? `${name}_Query` : null;
|
||||
return o.fn(
|
||||
[new o.FnParam(RENDER_FLAGS, o.NUMBER_TYPE), new o.FnParam(CONTEXT_NAME, null)],
|
||||
[
|
||||
|
Reference in New Issue
Block a user