refactor(ivy): define new `AttributeMarker.Template` marker (#29041)
This commit adds a new `AttributeMarker` type that will be used, in a future commit, to mark attributes as coming from an inline-template expansion, rather than the element that is being contained in the template. PR Close #29041
This commit is contained in:
parent
423ac01dcf
commit
e3a401d20c
|
@ -450,4 +450,29 @@ export const enum AttributeMarker {
|
|||
* ```
|
||||
*/
|
||||
Bindings = 3,
|
||||
|
||||
/**
|
||||
* Signals that the following attribute names were hoisted from an inline-template declaration.
|
||||
*
|
||||
* For example, given the following HTML:
|
||||
*
|
||||
* ```
|
||||
* <div *ngFor="let value of values; trackBy:trackBy" dirA [dirB]="value">
|
||||
* ```
|
||||
*
|
||||
* the generated code for the `template()` instruction would include:
|
||||
*
|
||||
* ```
|
||||
* ['dirA', '', AttributeMarker.Bindings, 'dirB', AttributeMarker.Template, 'ngFor', 'ngForOf',
|
||||
* 'ngForTrackBy', 'let-value']
|
||||
* ```
|
||||
*
|
||||
* while the generated code for the `element()` instruction inside the template function would
|
||||
* include:
|
||||
*
|
||||
* ```
|
||||
* ['dirA', '', AttributeMarker.Bindings, 'dirB']
|
||||
* ```
|
||||
*/
|
||||
Template = 4,
|
||||
}
|
||||
|
|
|
@ -1044,7 +1044,8 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
|||
* attrs = [prop, value, prop2, value2,
|
||||
* CLASSES, class1, class2,
|
||||
* STYLES, style1, value1, style2, value2,
|
||||
* BINDINGS, name1, name2, name3, ...]
|
||||
* BINDINGS, name1, name2, name3,
|
||||
* TEMPLATE, name4, name5, ...]
|
||||
* ```
|
||||
*
|
||||
* Note that this function will fully ignore all synthetic (@foo) attribute values
|
||||
|
@ -1068,8 +1069,8 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
|||
}
|
||||
}
|
||||
|
||||
// it's important that this occurs before BINDINGS because once `elementStart`
|
||||
// comes across the BINDINGS marker then it will continue reading each value as
|
||||
// it's important that this occurs before BINDINGS and TEMPLATE because once `elementStart`
|
||||
// comes across the BINDINGS or TEMPLATE markers then it will continue reading each value as
|
||||
// as single property value cell by cell.
|
||||
if (styles) {
|
||||
styles.populateInitialStylingAttrs(attrExprs);
|
||||
|
|
|
@ -17,7 +17,7 @@ import {getComponentDef, getDirectiveDef, getPipeDef} from './definition';
|
|||
import {NG_ELEMENT_ID} from './fields';
|
||||
import {DirectiveDef} from './interfaces/definition';
|
||||
import {NO_PARENT_INJECTOR, NodeInjectorFactory, PARENT_INJECTOR, RelativeInjectorLocation, RelativeInjectorLocationFlags, TNODE, isFactory} from './interfaces/injector';
|
||||
import {AttributeMarker, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeProviderIndexes, TNodeType} from './interfaces/node';
|
||||
import {TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeProviderIndexes, TNodeType, isNameOnlyAttributeMarker} from './interfaces/node';
|
||||
import {DECLARATION_VIEW, INJECTOR, LView, TData, TVIEW, TView, T_HOST} from './interfaces/view';
|
||||
import {assertNodeOfPossibleTypes} from './node_assert';
|
||||
import {getLView, getPreviousOrParentTNode, setTNodeAndViewData} from './state';
|
||||
|
@ -272,9 +272,10 @@ export function injectAttributeImpl(tNode: TNode, attrNameToInject: string): str
|
|||
if (attrs) {
|
||||
for (let i = 0; i < attrs.length; i = i + 2) {
|
||||
const attrName = attrs[i];
|
||||
if (attrName === AttributeMarker.Bindings) break;
|
||||
// TODO: What happens here if an attribute has a namespace?
|
||||
// TODO: What happens here if the attribute name happens to match a CSS class or style?
|
||||
// If we hit a `Bindings` or `Template` marker then we are done.
|
||||
if (isNameOnlyAttributeMarker(attrName)) break;
|
||||
// TODO(FW-1137): Skip namespaced attributes
|
||||
// TODO(FW-1139): supports classes/styles in @Attribute injection
|
||||
if (attrName == attrNameToInject) {
|
||||
return attrs[i + 1] as string;
|
||||
}
|
||||
|
|
|
@ -122,6 +122,35 @@ export const enum AttributeMarker {
|
|||
* ```
|
||||
*/
|
||||
Bindings = 3,
|
||||
|
||||
/**
|
||||
* Signals that the following attribute names were hoisted from an inline-template declaration.
|
||||
*
|
||||
* For example, given the following HTML:
|
||||
*
|
||||
* ```
|
||||
* <div *ngFor="let value of values; trackBy:trackBy" dirA [dirB]="value">
|
||||
* ```
|
||||
*
|
||||
* the generated code for the `template()` instruction would include:
|
||||
*
|
||||
* ```
|
||||
* ['dirA', '', AttributeMarker.Bindings, 'dirB', AttributeMarker.Template, 'ngFor', 'ngForOf',
|
||||
* 'ngForTrackBy', 'let-value']
|
||||
* ```
|
||||
*
|
||||
* while the generated code for the `element()` instruction inside the template function would
|
||||
* include:
|
||||
*
|
||||
* ```
|
||||
* ['dirA', '', AttributeMarker.Bindings, 'dirB']
|
||||
* ```
|
||||
*/
|
||||
Template = 4,
|
||||
}
|
||||
|
||||
export function isNameOnlyAttributeMarker(marker: string | AttributeMarker) {
|
||||
return marker === AttributeMarker.Bindings || marker === AttributeMarker.Template;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
import '../util/ng_dev_mode';
|
||||
|
||||
import {assertDefined, assertNotEqual} from '../util/assert';
|
||||
import {AttributeMarker, TAttributes, TNode, TNodeType, unusedValueExportToPlacateAjd as unused1} from './interfaces/node';
|
||||
|
||||
import {AttributeMarker, TAttributes, TNode, TNodeType, isNameOnlyAttributeMarker, unusedValueExportToPlacateAjd as unused1} from './interfaces/node';
|
||||
import {CssSelector, CssSelectorList, NG_PROJECT_AS_ATTR_NAME, SelectorFlags, unusedValueExportToPlacateAjd as unused2} from './interfaces/projection';
|
||||
import {getInitialClassNameValue} from './styling/class_and_style_bindings';
|
||||
|
||||
|
@ -61,7 +62,16 @@ export function isNodeMatchingSelector(
|
|||
ngDevMode && assertDefined(selector[0], 'Selector should have a tag name');
|
||||
let mode: SelectorFlags = SelectorFlags.ELEMENT;
|
||||
const nodeAttrs = tNode.attrs || [];
|
||||
const nameOnlyMarkerIdx = nodeAttrs.indexOf(AttributeMarker.Bindings);
|
||||
|
||||
// Find the index of first attribute that has no value, only a name.
|
||||
let nameOnlyMarkerIdx = nodeAttrs && nodeAttrs.length;
|
||||
for (let i = 0; i < nodeAttrs.length; i++) {
|
||||
const nodeAttr = nodeAttrs[i];
|
||||
if (isNameOnlyAttributeMarker(nodeAttr)) {
|
||||
nameOnlyMarkerIdx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// When processing ":not" selectors, we skip to the next ":not" if the
|
||||
// current one doesn't match
|
||||
|
@ -174,7 +184,7 @@ function findAttrIndexInNode(name: string, attrs: TAttributes | null): number {
|
|||
// NOTE(benlesh): will not find namespaced attributes. This is by design.
|
||||
i += 4;
|
||||
} else {
|
||||
if (maybeAttrName === AttributeMarker.Bindings) {
|
||||
if (isNameOnlyAttributeMarker(maybeAttrName)) {
|
||||
nameOnlyMode = true;
|
||||
}
|
||||
i += nameOnlyMode ? 1 : 2;
|
||||
|
|
|
@ -374,6 +374,9 @@
|
|||
{
|
||||
"name": "getLViewParent"
|
||||
},
|
||||
{
|
||||
"name": "getNameOnlyMarkerIndex"
|
||||
},
|
||||
{
|
||||
"name": "getNativeAnchorNode"
|
||||
},
|
||||
|
@ -494,6 +497,9 @@
|
|||
{
|
||||
"name": "isLView"
|
||||
},
|
||||
{
|
||||
"name": "isNameOnlyAttributeMarker"
|
||||
},
|
||||
{
|
||||
"name": "isNodeMatchingSelector"
|
||||
},
|
||||
|
@ -518,6 +524,9 @@
|
|||
{
|
||||
"name": "locateHostElement"
|
||||
},
|
||||
{
|
||||
"name": "matchTemplateAttribute"
|
||||
},
|
||||
{
|
||||
"name": "namespaceHTML"
|
||||
},
|
||||
|
|
|
@ -323,9 +323,21 @@
|
|||
{
|
||||
"name": "_c18"
|
||||
},
|
||||
{
|
||||
"name": "_c19"
|
||||
},
|
||||
{
|
||||
"name": "_c2"
|
||||
},
|
||||
{
|
||||
"name": "_c20"
|
||||
},
|
||||
{
|
||||
"name": "_c21"
|
||||
},
|
||||
{
|
||||
"name": "_c22"
|
||||
},
|
||||
{
|
||||
"name": "_c3"
|
||||
},
|
||||
|
@ -749,6 +761,9 @@
|
|||
{
|
||||
"name": "getMultiStylesStartIndex"
|
||||
},
|
||||
{
|
||||
"name": "getNameOnlyMarkerIndex"
|
||||
},
|
||||
{
|
||||
"name": "getNativeAnchorNode"
|
||||
},
|
||||
|
@ -983,6 +998,9 @@
|
|||
{
|
||||
"name": "isListLikeIterable"
|
||||
},
|
||||
{
|
||||
"name": "isNameOnlyAttributeMarker"
|
||||
},
|
||||
{
|
||||
"name": "isNodeMatchingSelector"
|
||||
},
|
||||
|
@ -1040,6 +1058,9 @@
|
|||
{
|
||||
"name": "markViewDirty"
|
||||
},
|
||||
{
|
||||
"name": "matchTemplateAttribute"
|
||||
},
|
||||
{
|
||||
"name": "namespaceHTML"
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue