refactor(ivy): move hostVars
/hostAttrs
from instruction to DirectiveDef
(#34683)
This change moves information from instructions to declarative position: - `ɵɵallocHostVars(vars)` => `DirectiveDef.hostVars` - `ɵɵelementHostAttrs(attrs)` => `DirectiveDef.hostAttrs` When merging directives it is necessary to know about `hostVars` and `hostAttrs`. Before this change the information was stored in the `hostBindings` function. This was problematic, because in order to get to the information the `hostBindings` would have to be executed. In order for `hostBindings` to be executed the directives would have to be instantiated. This means that the directive instantiation would happen before we had knowledge about the `hostAttrs` and as a result the directive could observe in the constructor that not all of the `hostAttrs` have been applied. This further complicates the runtime as we have to apply `hostAttrs` in parts over many invocations. `ɵɵallocHostVars` was unnecessarily complicated because it would have to update the `LView` (and Blueprint) while existing directives are already executing. By moving it out of `hostBindings` function we can access it statically and we can create correct `LView` (and Blueprint) in a single pass. This change only changes how the instructions are generated, but does not change the runtime much. (We cheat by emulating the old behavior by calling `ɵɵallocHostVars` and `ɵɵelementHostAttrs`) Subsequent change will refactor the runtime to take advantage of the static information. PR Close #34683
This commit is contained in:
@ -115,8 +115,6 @@ export class Identifiers {
|
||||
|
||||
static styleSanitizer: o.ExternalReference = {name: 'ɵɵstyleSanitizer', moduleName: CORE};
|
||||
|
||||
static elementHostAttrs: o.ExternalReference = {name: 'ɵɵelementHostAttrs', moduleName: CORE};
|
||||
|
||||
static containerCreate: o.ExternalReference = {name: 'ɵɵcontainer', moduleName: CORE};
|
||||
|
||||
static nextContext: o.ExternalReference = {name: 'ɵɵnextContext', moduleName: CORE};
|
||||
@ -129,8 +127,6 @@ export class Identifiers {
|
||||
|
||||
static disableBindings: o.ExternalReference = {name: 'ɵɵdisableBindings', moduleName: CORE};
|
||||
|
||||
static allocHostVars: o.ExternalReference = {name: 'ɵɵallocHostVars', moduleName: CORE};
|
||||
|
||||
static getCurrentView: o.ExternalReference = {name: 'ɵɵgetCurrentView', moduleName: CORE};
|
||||
|
||||
static textInterpolate: o.ExternalReference = {name: 'ɵɵtextInterpolate', moduleName: CORE};
|
||||
|
@ -67,7 +67,7 @@ function baseDirectiveFields(
|
||||
definitionMap.set(
|
||||
'hostBindings', createHostBindingsFunction(
|
||||
meta.host, meta.typeSourceSpan, bindingParser, constantPool,
|
||||
meta.selector || '', meta.name));
|
||||
meta.selector || '', meta.name, definitionMap));
|
||||
|
||||
// e.g 'inputs: {a: 'a'}`
|
||||
definitionMap.set('inputs', conditionallyCreateMapObjectLiteral(meta.inputs, true));
|
||||
@ -528,8 +528,8 @@ function createViewQueriesFunction(
|
||||
// Return a host binding function or null if one is not necessary.
|
||||
function createHostBindingsFunction(
|
||||
hostBindingsMetadata: R3HostMetadata, typeSourceSpan: ParseSourceSpan,
|
||||
bindingParser: BindingParser, constantPool: ConstantPool, selector: string,
|
||||
name?: string): o.Expression|null {
|
||||
bindingParser: BindingParser, constantPool: ConstantPool, selector: string, name: string,
|
||||
definitionMap: DefinitionMap): o.Expression|null {
|
||||
// Initialize hostVarsCount to number of bound host properties (interpolations illegal)
|
||||
const hostVarsCount = Object.keys(hostBindingsMetadata.properties).length;
|
||||
const elVarExp = o.variable('elIndex');
|
||||
@ -651,14 +651,7 @@ function createHostBindingsFunction(
|
||||
// to the host element alongside any of the provided host attributes that were
|
||||
// collected earlier.
|
||||
const hostAttrs = convertAttributesToExpressions(hostBindingsMetadata.attributes);
|
||||
const hostInstruction = styleBuilder.buildHostAttrsInstruction(null, hostAttrs, constantPool);
|
||||
if (hostInstruction && hostInstruction.calls.length > 0) {
|
||||
createStatements.push(
|
||||
chainedInstruction(
|
||||
hostInstruction.reference,
|
||||
hostInstruction.calls.map(call => convertStylingCall(call, bindingContext, bindingFn)))
|
||||
.toStmt());
|
||||
}
|
||||
styleBuilder.assignHostAttrs(hostAttrs, definitionMap);
|
||||
|
||||
if (styleBuilder.hasBindings) {
|
||||
// finally each binding that was registered in the statement above will need to be added to
|
||||
@ -681,8 +674,7 @@ function createHostBindingsFunction(
|
||||
}
|
||||
|
||||
if (totalHostVarsCount) {
|
||||
createStatements.unshift(
|
||||
o.importExpr(R3.allocHostVars).callFn([o.literal(totalHostVarsCount)]).toStmt());
|
||||
definitionMap.set('hostVars', o.literal(totalHostVarsCount));
|
||||
}
|
||||
|
||||
if (createStatements.length > 0 || updateStatements.length > 0) {
|
||||
|
@ -16,7 +16,7 @@ import {Identifiers as R3} from '../r3_identifiers';
|
||||
|
||||
import {hyphenate, parse as parseStyle} from './style_parser';
|
||||
import {ValueConverter} from './template';
|
||||
import {getInterpolationArgsLength} from './util';
|
||||
import {DefinitionMap, getInterpolationArgsLength} from './util';
|
||||
|
||||
const IMPORTANT_FLAG = '!important';
|
||||
|
||||
@ -279,27 +279,11 @@ export class StylingBuilder {
|
||||
* responsible for registering initial styles (within a directive hostBindings' creation block),
|
||||
* as well as any of the provided attribute values, to the directive host element.
|
||||
*/
|
||||
buildHostAttrsInstruction(
|
||||
sourceSpan: ParseSourceSpan|null, attrs: o.Expression[],
|
||||
constantPool: ConstantPool): StylingInstruction|null {
|
||||
assignHostAttrs(attrs: o.Expression[], definitionMap: DefinitionMap): void {
|
||||
if (this._directiveExpr && (attrs.length || this._hasInitialValues)) {
|
||||
return {
|
||||
reference: R3.elementHostAttrs,
|
||||
calls: [{
|
||||
sourceSpan,
|
||||
allocateBindingSlots: 0,
|
||||
params: () => {
|
||||
// params => elementHostAttrs(attrs)
|
||||
this.populateInitialStylingAttrs(attrs);
|
||||
const attrArray = !attrs.some(attr => attr instanceof o.WrappedNodeExpr) ?
|
||||
getConstantLiteralFromArray(constantPool, attrs) :
|
||||
o.literalArr(attrs);
|
||||
return [attrArray];
|
||||
}
|
||||
}]
|
||||
};
|
||||
this.populateInitialStylingAttrs(attrs);
|
||||
definitionMap.set('hostAttrs', o.literalArr(attrs));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user