fix(ivy): update compiler with latest runtime for view queries (#25061)
PR Close #25061
This commit is contained in:
parent
0bcf20c9fa
commit
1e28495c89
|
@ -963,16 +963,20 @@ describe('compiler compliance', () => {
|
|||
type: ViewQueryComponent,
|
||||
selectors: [["view-query-component"]],
|
||||
factory: function ViewQueryComponent_Factory() { return new ViewQueryComponent(); },
|
||||
template: function ViewQueryComponent_Template(rf, ctx) {
|
||||
var $tmp$;
|
||||
viewQuery: function ViewQueryComponent_Query(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵQ(0, SomeDirective, true);
|
||||
$r3$.ɵEe(1, "div", $e0_attrs$);
|
||||
}
|
||||
if (rf & 2) {
|
||||
var $tmp$;
|
||||
($r3$.ɵqR(($tmp$ = $r3$.ɵld(0))) && (ctx.someDir = $tmp$.first));
|
||||
}
|
||||
},
|
||||
template: function ViewQueryComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵEe(1, "div", $e0_attrs$);
|
||||
}
|
||||
},
|
||||
directives:[SomeDirective]
|
||||
});`;
|
||||
|
||||
|
|
|
@ -27,8 +27,8 @@ import {Render3ParseResult} from '../r3_template_transform';
|
|||
import {typeWithParameters} from '../util';
|
||||
|
||||
import {R3ComponentDef, R3ComponentMetadata, R3DirectiveDef, R3DirectiveMetadata, R3QueryMetadata} from './api';
|
||||
import {BindingScope, TemplateDefinitionBuilder} from './template';
|
||||
import {CONTEXT_NAME, DefinitionMap, ID_SEPARATOR, MEANING_SEPARATOR, TEMPORARY_NAME, asLiteral, conditionallyCreateMapObjectLiteral, getQueryPredicate, temporaryAllocator, unsupported} from './util';
|
||||
import {BindingScope, TemplateDefinitionBuilder, renderFlagCheckIfStmt} from './template';
|
||||
import {CONTEXT_NAME, DefinitionMap, ID_SEPARATOR, MEANING_SEPARATOR, RENDER_FLAGS, TEMPORARY_NAME, asLiteral, conditionallyCreateMapObjectLiteral, getQueryPredicate, temporaryAllocator, unsupported} from './util';
|
||||
|
||||
function baseDirectiveFields(
|
||||
meta: R3DirectiveMetadata, constantPool: ConstantPool,
|
||||
|
@ -138,6 +138,10 @@ export function compileComponentFromMetadata(
|
|||
directiveMatcher = matcher;
|
||||
}
|
||||
|
||||
if (meta.viewQueries.length) {
|
||||
definitionMap.set('viewQuery', createViewQueriesFunction(meta, constantPool));
|
||||
}
|
||||
|
||||
// e.g. `template: function MyComponent_Template(_ctx, _cm) {...}`
|
||||
const templateTypeName = meta.name;
|
||||
const templateName = templateTypeName ? `${templateTypeName}_Template` : null;
|
||||
|
@ -322,32 +326,22 @@ function selectorsFromGlobalMetadata(
|
|||
return o.NULL_EXPR;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param meta
|
||||
* @param constantPool
|
||||
*/
|
||||
function createQueryDefinitions(
|
||||
queries: R3QueryMetadata[], constantPool: ConstantPool): o.Expression[]|undefined {
|
||||
const queryDefinitions: o.Expression[] = [];
|
||||
for (let i = 0; i < queries.length; i++) {
|
||||
const query = queries[i];
|
||||
const predicate = getQueryPredicate(query, constantPool);
|
||||
function createQueryDefinition(
|
||||
query: R3QueryMetadata, constantPool: ConstantPool, idx: number | null): o.Expression {
|
||||
const predicate = getQueryPredicate(query, constantPool);
|
||||
|
||||
// e.g. r3.Q(null, somePredicate, false) or r3.Q(null, ['div'], false)
|
||||
const parameters = [
|
||||
o.literal(null, o.INFERRED_TYPE),
|
||||
predicate,
|
||||
o.literal(query.descendants),
|
||||
];
|
||||
// e.g. r3.Q(null, somePredicate, false) or r3.Q(0, ['div'], false)
|
||||
const parameters = [
|
||||
o.literal(idx, o.INFERRED_TYPE),
|
||||
predicate,
|
||||
o.literal(query.descendants),
|
||||
];
|
||||
|
||||
if (query.read) {
|
||||
parameters.push(query.read);
|
||||
}
|
||||
|
||||
queryDefinitions.push(o.importExpr(R3.query).callFn(parameters));
|
||||
if (query.read) {
|
||||
parameters.push(query.read);
|
||||
}
|
||||
return queryDefinitions.length > 0 ? queryDefinitions : undefined;
|
||||
|
||||
return o.importExpr(R3.query).callFn(parameters);
|
||||
}
|
||||
|
||||
// Turn a directive selector into an R3-compatible selector for directive def
|
||||
|
@ -371,11 +365,10 @@ function createHostAttributesArray(meta: R3DirectiveMetadata): o.Expression|null
|
|||
// Return a contentQueries function or null if one is not necessary.
|
||||
function createContentQueriesFunction(
|
||||
meta: R3DirectiveMetadata, constantPool: ConstantPool): o.Expression|null {
|
||||
const queryDefinitions = createQueryDefinitions(meta.queries, constantPool);
|
||||
|
||||
if (queryDefinitions) {
|
||||
const statements: o.Statement[] = queryDefinitions.map((qd: o.Expression) => {
|
||||
return o.importExpr(R3.registerContentQuery).callFn([qd]).toStmt();
|
||||
if (meta.queries.length) {
|
||||
const statements: o.Statement[] = meta.queries.map((query: R3QueryMetadata) => {
|
||||
const queryDefinition = createQueryDefinition(query, constantPool, null);
|
||||
return o.importExpr(R3.registerContentQuery).callFn([queryDefinition]).toStmt();
|
||||
});
|
||||
const typeName = meta.name;
|
||||
return o.fn(
|
||||
|
@ -426,6 +419,40 @@ function createContentQueriesRefreshFunction(meta: R3DirectiveMetadata): o.Expre
|
|||
return null;
|
||||
}
|
||||
|
||||
// Define and update any view queries
|
||||
function createViewQueriesFunction(
|
||||
meta: R3ComponentMetadata, constantPool: ConstantPool): o.Expression {
|
||||
const createStatements: o.Statement[] = [];
|
||||
const updateStatements: o.Statement[] = [];
|
||||
const tempAllocator = temporaryAllocator(updateStatements, TEMPORARY_NAME);
|
||||
|
||||
for (let i = 0; i < meta.viewQueries.length; i++) {
|
||||
const query = meta.viewQueries[i];
|
||||
|
||||
// creation, e.g. r3.Q(0, somePredicate, true);
|
||||
const queryDefinition = createQueryDefinition(query, constantPool, i);
|
||||
createStatements.push(queryDefinition.toStmt());
|
||||
|
||||
// update, e.g. (r3.qR(tmp = r3.ɵld(0)) && (ctx.someDir = tmp));
|
||||
const temporary = tempAllocator();
|
||||
const getQueryList = o.importExpr(R3.load).callFn([o.literal(i)]);
|
||||
const refresh = o.importExpr(R3.queryRefresh).callFn([temporary.set(getQueryList)]);
|
||||
const updateDirective = o.variable(CONTEXT_NAME)
|
||||
.prop(query.propertyName)
|
||||
.set(query.first ? temporary.prop('first') : temporary);
|
||||
updateStatements.push(refresh.and(updateDirective).toStmt());
|
||||
}
|
||||
|
||||
const viewQueryFnName = meta.name ? `${meta.name}_Query` : null;
|
||||
return o.fn(
|
||||
[new o.FnParam(RENDER_FLAGS, o.NUMBER_TYPE), new o.FnParam(CONTEXT_NAME, null)],
|
||||
[
|
||||
renderFlagCheckIfStmt(core.RenderFlags.Create, createStatements),
|
||||
renderFlagCheckIfStmt(core.RenderFlags.Update, updateStatements)
|
||||
],
|
||||
o.INFERRED_TYPE, null, viewQueryFnName);
|
||||
}
|
||||
|
||||
// Return a host binding function or null if one is not necessary.
|
||||
function createHostBindingsFunction(
|
||||
meta: R3DirectiveMetadata, bindingParser: BindingParser): o.Expression|null {
|
||||
|
|
|
@ -46,6 +46,12 @@ function mapBindingToInstruction(type: BindingType): o.ExternalReference|undefin
|
|||
}
|
||||
}
|
||||
|
||||
// if (rf & flags) { .. }
|
||||
export function renderFlagCheckIfStmt(
|
||||
flags: core.RenderFlags, statements: o.Statement[]): o.IfStmt {
|
||||
return o.ifStmt(o.variable(RENDER_FLAGS).bitwiseAnd(o.literal(flags), null, false), statements);
|
||||
}
|
||||
|
||||
export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver {
|
||||
private _dataIndex = 0;
|
||||
private _bindingContext = 0;
|
||||
|
@ -54,7 +60,6 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
|||
private _variableCode: o.Statement[] = [];
|
||||
private _bindingCode: o.Statement[] = [];
|
||||
private _postfixCode: o.Statement[] = [];
|
||||
private _temporary = temporaryAllocator(this._prefixCode, TEMPORARY_NAME);
|
||||
private _valueConverter: ValueConverter;
|
||||
private _unsupported = unsupported;
|
||||
private _bindingScope: BindingScope;
|
||||
|
@ -75,6 +80,9 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
|||
private directiveMatcher: SelectorMatcher|null, private directives: Set<o.Expression>,
|
||||
private pipeTypeByName: Map<string, o.Expression>, private pipes: Set<o.Expression>,
|
||||
private _namespace: o.ExternalReference) {
|
||||
// view queries can take up space in data and allocation happens earlier (in the "viewQuery"
|
||||
// function)
|
||||
this._dataIndex = viewQueries.length;
|
||||
this._bindingScope =
|
||||
parentBindingScope.nestedScope((lhsVar: o.ReadVarExpr, expression: o.Expression) => {
|
||||
this._bindingCode.push(
|
||||
|
@ -127,32 +135,6 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
|||
this.instruction(this._creationCode, null, R3.projectionDef, ...parameters);
|
||||
}
|
||||
|
||||
// Define and update any view queries
|
||||
for (let query of this.viewQueries) {
|
||||
// e.g. r3.Q(0, somePredicate, true);
|
||||
const querySlot = this.allocateDataSlot();
|
||||
const predicate = getQueryPredicate(query, this.constantPool);
|
||||
const args: o.Expression[] = [
|
||||
o.literal(querySlot, o.INFERRED_TYPE),
|
||||
predicate,
|
||||
o.literal(query.descendants, o.INFERRED_TYPE),
|
||||
];
|
||||
|
||||
if (query.read) {
|
||||
args.push(query.read);
|
||||
}
|
||||
this.instruction(this._creationCode, null, R3.query, ...args);
|
||||
|
||||
// (r3.qR(tmp = r3.ɵld(0)) && (ctx.someDir = tmp));
|
||||
const temporary = this._temporary();
|
||||
const getQueryList = o.importExpr(R3.load).callFn([o.literal(querySlot)]);
|
||||
const refresh = o.importExpr(R3.queryRefresh).callFn([temporary.set(getQueryList)]);
|
||||
const updateDirective = o.variable(CONTEXT_NAME)
|
||||
.prop(query.propertyName)
|
||||
.set(query.first ? temporary.prop('first') : temporary);
|
||||
this._bindingCode.push(refresh.and(updateDirective).toStmt());
|
||||
}
|
||||
|
||||
t.visitAll(this, nodes);
|
||||
|
||||
if (this._pureFunctionSlots > 0) {
|
||||
|
@ -161,15 +143,11 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
|||
}
|
||||
|
||||
const creationCode = this._creationCode.length > 0 ?
|
||||
[o.ifStmt(
|
||||
o.variable(RENDER_FLAGS).bitwiseAnd(o.literal(core.RenderFlags.Create), null, false),
|
||||
this._creationCode)] :
|
||||
[renderFlagCheckIfStmt(core.RenderFlags.Create, this._creationCode)] :
|
||||
[];
|
||||
|
||||
const updateCode = this._bindingCode.length > 0 ?
|
||||
[o.ifStmt(
|
||||
o.variable(RENDER_FLAGS).bitwiseAnd(o.literal(core.RenderFlags.Update), null, false),
|
||||
this._bindingCode)] :
|
||||
[renderFlagCheckIfStmt(core.RenderFlags.Update, this._bindingCode)] :
|
||||
[];
|
||||
|
||||
// Generate maps of placeholder name to node indexes
|
||||
|
|
Loading…
Reference in New Issue