2018-01-09 18:38:17 -08:00
|
|
|
/**
|
|
|
|
* @license
|
|
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
|
|
* found in the LICENSE file at https://angular.io/license
|
|
|
|
*/
|
2019-05-08 16:30:28 -07:00
|
|
|
import {TStylingContext} from '../styling_next/interfaces';
|
2019-04-08 22:47:23 +02:00
|
|
|
import {CssSelector} from './projection';
|
2019-01-21 14:55:37 +01:00
|
|
|
import {RNode} from './renderer';
|
2018-09-28 12:38:16 -07:00
|
|
|
import {StylingContext} from './styling';
|
2018-11-21 21:14:06 -08:00
|
|
|
import {LView, TView} from './view';
|
2018-01-09 18:38:17 -08:00
|
|
|
|
2018-06-06 13:38:18 -07:00
|
|
|
|
2018-01-09 18:38:17 -08:00
|
|
|
/**
|
2019-03-15 13:24:52 -07:00
|
|
|
* TNodeType corresponds to the {@link TNode} `type` property.
|
2018-01-09 18:38:17 -08:00
|
|
|
*/
|
2018-05-17 12:54:57 -07:00
|
|
|
export const enum TNodeType {
|
2019-03-15 13:24:52 -07:00
|
|
|
/**
|
|
|
|
* The TNode contains information about an {@link LContainer} for embedded views.
|
|
|
|
*/
|
|
|
|
Container = 0,
|
|
|
|
/**
|
|
|
|
* The TNode contains information about an `<ng-content>` projection
|
|
|
|
*/
|
|
|
|
Projection = 1,
|
|
|
|
/**
|
|
|
|
* The TNode contains information about an {@link LView}
|
|
|
|
*/
|
|
|
|
View = 2,
|
|
|
|
/**
|
|
|
|
* The TNode contains information about a DOM element aka {@link RNode}.
|
|
|
|
*/
|
|
|
|
Element = 3,
|
|
|
|
/**
|
|
|
|
* The TNode contains information about an `<ng-container>` element {@link RNode}.
|
|
|
|
*/
|
|
|
|
ElementContainer = 4,
|
|
|
|
/**
|
|
|
|
* The TNode contains information about an ICU comment used in `i18n`.
|
|
|
|
*/
|
|
|
|
IcuContainer = 5,
|
2018-01-09 18:38:17 -08:00
|
|
|
}
|
|
|
|
|
2018-03-20 19:06:49 -07:00
|
|
|
/**
|
2018-04-12 14:52:00 -07:00
|
|
|
* Corresponds to the TNode.flags property.
|
2018-03-20 19:06:49 -07:00
|
|
|
*/
|
2018-03-25 21:32:39 -07:00
|
|
|
export const enum TNodeFlags {
|
2018-07-03 20:04:36 -07:00
|
|
|
/** This bit is set if the node is a component */
|
2019-06-05 20:47:21 +02:00
|
|
|
isComponent = 0b000001,
|
2018-07-03 20:04:36 -07:00
|
|
|
|
|
|
|
/** This bit is set if the node has been projected */
|
2019-06-05 20:47:21 +02:00
|
|
|
isProjected = 0b000010,
|
2018-03-25 21:32:39 -07:00
|
|
|
|
2019-01-31 16:02:19 +01:00
|
|
|
/** This bit is set if any directive on this node has content queries */
|
2019-06-05 20:47:21 +02:00
|
|
|
hasContentQuery = 0b000100,
|
2018-08-09 10:00:07 -07:00
|
|
|
|
2019-02-08 15:03:54 -08:00
|
|
|
/** This bit is set if the node has any "class" inputs */
|
2019-06-05 20:47:21 +02:00
|
|
|
hasClassInput = 0b001000,
|
2019-02-08 15:03:54 -08:00
|
|
|
|
|
|
|
/** This bit is set if the node has any "style" inputs */
|
2019-06-05 20:47:21 +02:00
|
|
|
hasStyleInput = 0b010000,
|
|
|
|
|
|
|
|
/** This bit is set if the node has been detached by i18n */
|
|
|
|
isDetached = 0b100000,
|
2018-03-25 21:32:39 -07:00
|
|
|
}
|
2018-03-20 19:06:49 -07:00
|
|
|
|
2018-10-18 09:23:18 +02:00
|
|
|
/**
|
|
|
|
* Corresponds to the TNode.providerIndexes property.
|
|
|
|
*/
|
|
|
|
export const enum TNodeProviderIndexes {
|
|
|
|
/** The index of the first provider on this node is encoded on the least significant bits */
|
|
|
|
ProvidersStartIndexMask = 0b00000000000000001111111111111111,
|
|
|
|
|
|
|
|
/** The count of view providers from the component on this node is encoded on the 16 most
|
|
|
|
significant bits */
|
|
|
|
CptViewProvidersCountShift = 16,
|
|
|
|
CptViewProvidersCountShifter = 0b00000000000000010000000000000000,
|
|
|
|
}
|
2018-05-04 15:58:42 +02:00
|
|
|
/**
|
2018-12-13 15:51:47 -08:00
|
|
|
* A set of marker values to be used in the attributes arrays. These markers indicate that some
|
2018-05-04 15:58:42 +02:00
|
|
|
* items are not regular attributes and the processing should be adapted accordingly.
|
|
|
|
*/
|
|
|
|
export const enum AttributeMarker {
|
2018-06-08 15:25:39 -07:00
|
|
|
/**
|
|
|
|
* Marker indicates that the following 3 values in the attributes array are:
|
|
|
|
* namespaceUri, attributeName, attributeValue
|
|
|
|
* in that order.
|
|
|
|
*/
|
|
|
|
NamespaceURI = 0,
|
2018-05-04 15:58:42 +02:00
|
|
|
|
2018-12-13 15:51:47 -08:00
|
|
|
/**
|
|
|
|
* Signals class declaration.
|
|
|
|
*
|
|
|
|
* Each value following `Classes` designates a class name to include on the element.
|
|
|
|
* ## Example:
|
|
|
|
*
|
|
|
|
* Given:
|
|
|
|
* ```
|
|
|
|
* <div class="foo bar baz">...<d/vi>
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* the generated code is:
|
|
|
|
* ```
|
|
|
|
* var _c1 = [AttributeMarker.Classes, 'foo', 'bar', 'baz'];
|
|
|
|
* ```
|
|
|
|
*/
|
|
|
|
Classes = 1,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Signals style declaration.
|
|
|
|
*
|
|
|
|
* Each pair of values following `Styles` designates a style name and value to include on the
|
|
|
|
* element.
|
|
|
|
* ## Example:
|
|
|
|
*
|
|
|
|
* Given:
|
|
|
|
* ```
|
|
|
|
* <div style="width:100px; height:200px; color:red">...</div>
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* the generated code is:
|
|
|
|
* ```
|
|
|
|
* var _c1 = [AttributeMarker.Styles, 'width', '100px', 'height'. '200px', 'color', 'red'];
|
|
|
|
* ```
|
|
|
|
*/
|
|
|
|
Styles = 2,
|
|
|
|
|
2018-05-04 15:58:42 +02:00
|
|
|
/**
|
2019-03-07 08:31:31 +00:00
|
|
|
* Signals that the following attribute names were extracted from input or output bindings.
|
|
|
|
*
|
|
|
|
* For example, given the following HTML:
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
* <div moo="car" [foo]="exp" (bar)="doSth()">
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* the generated code is:
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
* var _c1 = ['moo', 'car', AttributeMarker.Bindings, 'foo', 'bar'];
|
|
|
|
* ```
|
2018-05-04 15:58:42 +02:00
|
|
|
*/
|
2019-03-07 08:31:31 +00:00
|
|
|
Bindings = 3,
|
2019-03-07 08:31:31 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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,
|
2019-04-08 22:47:23 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Signals that the following attribute is `ngProjectAs` and its value is a parsed `CssSelector`.
|
|
|
|
*
|
|
|
|
* For example, given the following HTML:
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
* <h1 attr="value" ngProjectAs="[title]">
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* the generated code for the `element()` instruction would include:
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
* ['attr', 'value', AttributeMarker.ProjectAs, ['', 'title', '']]
|
|
|
|
* ```
|
|
|
|
*/
|
2019-05-15 17:08:50 +02:00
|
|
|
ProjectAs = 5,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Signals that the following attribute will be translated by runtime i18n
|
|
|
|
*
|
|
|
|
* For example, given the following HTML:
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
* <div moo="car" foo="value" i18n-foo [bar]="binding" i18n-bar>
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* the generated code is:
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
* var _c1 = ['moo', 'car', AttributeMarker.I18n, 'foo', 'bar'];
|
|
|
|
*/
|
2019-07-13 13:34:34 +02:00
|
|
|
I18n = 6,
|
2019-03-07 08:31:31 +00:00
|
|
|
}
|
|
|
|
|
2018-05-04 15:58:42 +02:00
|
|
|
/**
|
|
|
|
* A combination of:
|
2019-04-08 22:47:23 +02:00
|
|
|
* - Attribute names and values.
|
|
|
|
* - Special markers acting as flags to alter attributes processing.
|
|
|
|
* - Parsed ngProjectAs selectors.
|
2018-05-04 15:58:42 +02:00
|
|
|
*/
|
2019-04-08 22:47:23 +02:00
|
|
|
export type TAttributes = (string | AttributeMarker | CssSelector)[];
|
2018-05-04 15:58:42 +02:00
|
|
|
|
2018-01-09 18:38:17 -08:00
|
|
|
/**
|
2018-10-12 18:49:00 -07:00
|
|
|
* Binding data (flyweight) for a particular node that is shared between all templates
|
2018-01-09 18:38:17 -08:00
|
|
|
* of a specific type.
|
|
|
|
*
|
|
|
|
* If a property is:
|
|
|
|
* - PropertyAliases: that property's data was generated and this is it
|
|
|
|
* - Null: that property's data was already generated and nothing was found.
|
|
|
|
* - Undefined: that property's data has not yet been generated
|
|
|
|
*
|
|
|
|
* see: https://en.wikipedia.org/wiki/Flyweight_pattern for more on the Flyweight pattern
|
|
|
|
*/
|
|
|
|
export interface TNode {
|
2018-05-17 12:54:57 -07:00
|
|
|
/** The type of the TNode. See TNodeType. */
|
|
|
|
type: TNodeType;
|
|
|
|
|
2018-05-11 20:57:37 -07:00
|
|
|
/**
|
2018-11-21 21:14:06 -08:00
|
|
|
* Index of the TNode in TView.data and corresponding native element in LView.
|
2018-05-11 20:57:37 -07:00
|
|
|
*
|
2018-10-12 18:49:00 -07:00
|
|
|
* This is necessary to get from any TNode to its corresponding native element when
|
2018-05-11 20:57:37 -07:00
|
|
|
* traversing the node tree.
|
2018-05-16 05:56:01 -07:00
|
|
|
*
|
2018-06-01 14:46:28 -07:00
|
|
|
* If index is -1, this is a dynamically created container node or embedded view node.
|
2018-05-11 20:57:37 -07:00
|
|
|
*/
|
2018-06-01 14:46:28 -07:00
|
|
|
index: number;
|
2018-05-11 20:57:37 -07:00
|
|
|
|
2018-09-28 21:26:45 -07:00
|
|
|
/**
|
2018-11-21 21:14:06 -08:00
|
|
|
* The index of the closest injector in this node's LView.
|
2018-09-28 21:26:45 -07:00
|
|
|
*
|
|
|
|
* If the index === -1, there is no injector on this node or any ancestor node in this view.
|
|
|
|
*
|
|
|
|
* If the index !== -1, it is the index of this node's injector OR the index of a parent injector
|
|
|
|
* in the same view. We pass the parent injector index down the node tree of a view so it's
|
|
|
|
* possible to find the parent injector without walking a potentially deep node tree. Injector
|
|
|
|
* indices are not set across view boundaries because there could be multiple component hosts.
|
|
|
|
*
|
|
|
|
* If tNode.injectorIndex === tNode.parent.injectorIndex, then the index belongs to a parent
|
|
|
|
* injector.
|
|
|
|
*/
|
|
|
|
injectorIndex: number;
|
|
|
|
|
2018-03-20 19:06:49 -07:00
|
|
|
/**
|
2018-11-28 15:54:38 -08:00
|
|
|
* Stores starting index of the directives.
|
|
|
|
*/
|
|
|
|
directiveStart: number;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stores final exclusive index of the directives.
|
|
|
|
*/
|
|
|
|
directiveEnd: number;
|
|
|
|
|
2019-01-24 08:53:00 -08:00
|
|
|
/**
|
|
|
|
* Stores the first index where property binding metadata is stored for
|
|
|
|
* this node.
|
|
|
|
*/
|
|
|
|
propertyMetadataStartIndex: number;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stores the exclusive final index where property binding metadata is
|
|
|
|
* stored for this node.
|
|
|
|
*/
|
|
|
|
propertyMetadataEndIndex: number;
|
|
|
|
|
2018-11-28 15:54:38 -08:00
|
|
|
/**
|
2019-02-08 15:03:54 -08:00
|
|
|
* Stores if Node isComponent, isProjected, hasContentQuery, hasClassInput and hasStyleInput
|
2018-03-20 19:06:49 -07:00
|
|
|
*/
|
|
|
|
flags: TNodeFlags;
|
|
|
|
|
2018-10-18 09:23:18 +02:00
|
|
|
/**
|
|
|
|
* This number stores two values using its bits:
|
|
|
|
*
|
|
|
|
* - the index of the first provider on that node (first 16 bits)
|
|
|
|
* - the count of view providers from the component on this node (last 16 bits)
|
|
|
|
*/
|
2018-11-28 15:54:38 -08:00
|
|
|
// TODO(misko): break this into actual vars.
|
2018-10-18 09:23:18 +02:00
|
|
|
providerIndexes: TNodeProviderIndexes;
|
|
|
|
|
2018-01-09 18:38:17 -08:00
|
|
|
/** The tag name associated with this node. */
|
|
|
|
tagName: string|null;
|
|
|
|
|
|
|
|
/**
|
2018-05-04 15:58:42 +02:00
|
|
|
* Attributes associated with an element. We need to store attributes to support various use-cases
|
|
|
|
* (attribute injection, content projection with selectors, directives matching).
|
|
|
|
* Attributes are stored statically because reading them from the DOM would be way too slow for
|
|
|
|
* content projection and queries.
|
2018-01-09 18:38:17 -08:00
|
|
|
*
|
2018-05-04 15:58:42 +02:00
|
|
|
* Since attrs will always be calculated first, they will never need to be marked undefined by
|
|
|
|
* other instructions.
|
2018-01-09 18:38:17 -08:00
|
|
|
*
|
2018-05-04 15:58:42 +02:00
|
|
|
* For regular attributes a name of an attribute and its value alternate in the array.
|
2018-01-09 18:38:17 -08:00
|
|
|
* e.g. ['role', 'checkbox']
|
2018-05-04 15:58:42 +02:00
|
|
|
* This array can contain flags that will indicate "special attributes" (attributes with
|
|
|
|
* namespaces, attributes extracted from bindings and outputs).
|
2018-01-09 18:38:17 -08:00
|
|
|
*/
|
2018-05-04 15:58:42 +02:00
|
|
|
attrs: TAttributes|null;
|
2018-01-09 18:38:17 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A set of local names under which a given element is exported in a template and
|
|
|
|
* visible to queries. An entry in this array can be created for different reasons:
|
|
|
|
* - an element itself is referenced, ex.: `<div #foo>`
|
|
|
|
* - a component is referenced, ex.: `<my-cmpt #foo>`
|
|
|
|
* - a directive is referenced, ex.: `<my-cmpt #foo="directiveExportAs">`.
|
|
|
|
*
|
|
|
|
* A given element might have different local names and those names can be associated
|
|
|
|
* with a directive. We store local names at even indexes while odd indexes are reserved
|
|
|
|
* for directive index in a view (or `-1` if there is no associated directive).
|
|
|
|
*
|
|
|
|
* Some examples:
|
|
|
|
* - `<div #foo>` => `["foo", -1]`
|
|
|
|
* - `<my-cmpt #foo>` => `["foo", myCmptIdx]`
|
|
|
|
* - `<my-cmpt #foo #bar="directiveExportAs">` => `["foo", myCmptIdx, "bar", directiveIdx]`
|
|
|
|
* - `<div #foo #bar="directiveExportAs">` => `["foo", -1, "bar", directiveIdx]`
|
|
|
|
*/
|
|
|
|
localNames: (string|number)[]|null;
|
|
|
|
|
2018-02-07 22:19:24 -08:00
|
|
|
/** Information about input properties that need to be set once from attribute data. */
|
2018-01-09 18:38:17 -08:00
|
|
|
initialInputs: InitialInputData|null|undefined;
|
|
|
|
|
2018-02-07 22:19:24 -08:00
|
|
|
/**
|
|
|
|
* Input data for all directives on this node.
|
|
|
|
*
|
|
|
|
* - `undefined` means that the prop has not been initialized yet,
|
|
|
|
* - `null` means that the prop has been initialized but no inputs have been found.
|
|
|
|
*/
|
2018-01-09 18:38:17 -08:00
|
|
|
inputs: PropertyAliases|null|undefined;
|
|
|
|
|
2018-02-07 22:19:24 -08:00
|
|
|
/**
|
|
|
|
* Output data for all directives on this node.
|
|
|
|
*
|
|
|
|
* - `undefined` means that the prop has not been initialized yet,
|
|
|
|
* - `null` means that the prop has been initialized but no outputs have been found.
|
|
|
|
*/
|
2018-01-09 18:38:17 -08:00
|
|
|
outputs: PropertyAliases|null|undefined;
|
|
|
|
|
|
|
|
/**
|
2018-04-26 10:44:49 -07:00
|
|
|
* The TView or TViews attached to this node.
|
2018-01-09 18:38:17 -08:00
|
|
|
*
|
2018-10-12 18:49:00 -07:00
|
|
|
* If this TNode corresponds to an LContainer with inline views, the container will
|
2018-04-26 10:44:49 -07:00
|
|
|
* need to store separate static data for each of its view blocks (TView[]). Otherwise,
|
|
|
|
* nodes in inline views with the same index as nodes in their parent views will overwrite
|
|
|
|
* each other, as they are in the same template.
|
2018-01-09 18:38:17 -08:00
|
|
|
*
|
2018-04-26 10:44:49 -07:00
|
|
|
* Each index in this array corresponds to the static data for a certain
|
|
|
|
* view. So if you had V(0) and V(1) in a container, you might have:
|
|
|
|
*
|
|
|
|
* [
|
|
|
|
* [{tagName: 'div', attrs: ...}, null], // V(0) TView
|
|
|
|
* [{tagName: 'button', attrs ...}, null] // V(1) TView
|
|
|
|
*
|
2018-10-12 18:49:00 -07:00
|
|
|
* If this TNode corresponds to an LContainer with a template (e.g. structural
|
2018-04-26 10:44:49 -07:00
|
|
|
* directive), the template's TView will be stored here.
|
|
|
|
*
|
2018-10-12 18:49:00 -07:00
|
|
|
* If this TNode corresponds to an element, tViews will be null .
|
2018-01-09 18:38:17 -08:00
|
|
|
*/
|
2018-04-26 10:44:49 -07:00
|
|
|
tViews: TView|TView[]|null;
|
2018-05-11 20:57:37 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The next sibling node. Necessary so we can propagate through the root nodes of a view
|
|
|
|
* to insert them or remove them from the DOM.
|
|
|
|
*/
|
|
|
|
next: TNode|null;
|
2018-05-16 05:56:01 -07:00
|
|
|
|
2019-03-06 14:01:02 +01:00
|
|
|
/**
|
|
|
|
* The next projected sibling. Since in Angular content projection works on the node-by-node basis
|
|
|
|
* the act of projecting nodes might change nodes relationship at the insertion point (target
|
|
|
|
* view). At the same time we need to keep initial relationship between nodes as expressed in
|
|
|
|
* content view.
|
|
|
|
*/
|
|
|
|
projectionNext: TNode|null;
|
|
|
|
|
2018-05-24 13:13:51 -07:00
|
|
|
/**
|
|
|
|
* First child of the current node.
|
|
|
|
*
|
|
|
|
* For component nodes, the child will always be a ContentChild (in same view).
|
|
|
|
* For embedded view nodes, the child will be in their child view.
|
|
|
|
*/
|
|
|
|
child: TNode|null;
|
|
|
|
|
2018-05-29 15:08:30 -07:00
|
|
|
/**
|
|
|
|
* Parent node (in the same view only).
|
|
|
|
*
|
|
|
|
* We need a reference to a node's parent so we can append the node to its parent's native
|
|
|
|
* element at the appropriate time.
|
|
|
|
*
|
|
|
|
* If the parent would be in a different view (e.g. component host), this property will be null.
|
|
|
|
* It's important that we don't try to cross component boundaries when retrieving the parent
|
|
|
|
* because the parent will change (e.g. index, attrs) depending on where the component was
|
|
|
|
* used (and thus shouldn't be stored on TNode). In these cases, we retrieve the parent through
|
|
|
|
* LView.node instead (which will be instance-specific).
|
|
|
|
*
|
|
|
|
* If this is an inline view node (V), the parent will be its container.
|
|
|
|
*/
|
|
|
|
parent: TElementNode|TContainerNode|null;
|
|
|
|
|
2018-06-19 12:45:00 -07:00
|
|
|
stylingTemplate: StylingContext|null;
|
2018-07-03 20:04:36 -07:00
|
|
|
/**
|
|
|
|
* List of projected TNodes for a given component host element OR index into the said nodes.
|
|
|
|
*
|
|
|
|
* For easier discussion assume this example:
|
|
|
|
* `<parent>`'s view definition:
|
|
|
|
* ```
|
|
|
|
* <child id="c1">content1</child>
|
|
|
|
* <child id="c2"><span>content2</span></child>
|
|
|
|
* ```
|
|
|
|
* `<child>`'s view definition:
|
|
|
|
* ```
|
|
|
|
* <ng-content id="cont1"></ng-content>
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* If `Array.isArray(projection)` then `TNode` is a host element:
|
|
|
|
* - `projection` stores the content nodes which are to be projected.
|
|
|
|
* - The nodes represent categories defined by the selector: For example:
|
|
|
|
* `<ng-content/><ng-content select="abc"/>` would represent the heads for `<ng-content/>`
|
|
|
|
* and `<ng-content select="abc"/>` respectively.
|
|
|
|
* - The nodes we store in `projection` are heads only, we used `.next` to get their
|
|
|
|
* siblings.
|
|
|
|
* - The nodes `.next` is sorted/rewritten as part of the projection setup.
|
|
|
|
* - `projection` size is equal to the number of projections `<ng-content>`. The size of
|
|
|
|
* `c1` will be `1` because `<child>` has only one `<ng-content>`.
|
|
|
|
* - we store `projection` with the host (`c1`, `c2`) rather than the `<ng-content>` (`cont1`)
|
|
|
|
* because the same component (`<child>`) can be used in multiple locations (`c1`, `c2`) and as
|
|
|
|
* a result have different set of nodes to project.
|
|
|
|
* - without `projection` it would be difficult to efficiently traverse nodes to be projected.
|
|
|
|
*
|
|
|
|
* If `typeof projection == 'number'` then `TNode` is a `<ng-content>` element:
|
|
|
|
* - `projection` is an index of the host's `projection`Nodes.
|
|
|
|
* - This would return the first head node to project:
|
|
|
|
* `getHost(currentTNode).projection[currentTNode.projection]`.
|
|
|
|
* - When projecting nodes the parent node retrieved may be a `<ng-content>` node, in which case
|
2019-06-07 20:46:11 -07:00
|
|
|
* the process is recursive in nature.
|
2019-01-21 14:55:37 +01:00
|
|
|
*
|
|
|
|
* If `projection` is of type `RNode[][]` than we have a collection of native nodes passed as
|
|
|
|
* projectable nodes during dynamic component creation.
|
2018-07-03 20:04:36 -07:00
|
|
|
*/
|
2019-01-21 14:55:37 +01:00
|
|
|
projection: (TNode|RNode[])[]|number|null;
|
2019-02-08 15:03:54 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A buffer of functions that will be called once `elementEnd` (or `element`) completes.
|
|
|
|
*
|
|
|
|
* Due to the nature of how directives work in Angular, some directive code may
|
|
|
|
* need to fire after any template-level code runs. If present, this array will
|
|
|
|
* be flushed (each function will be invoked) once the associated element is
|
|
|
|
* created.
|
|
|
|
*
|
|
|
|
* If an element is created multiple times then this function will be populated
|
|
|
|
* with functions each time the creation block is called.
|
|
|
|
*/
|
|
|
|
onElementCreationFns: Function[]|null;
|
2019-05-08 16:30:28 -07:00
|
|
|
// TODO (matsko): rename this to `styles` once the old styling impl is gone
|
|
|
|
newStyles: TStylingContext|null;
|
|
|
|
// TODO (matsko): rename this to `classes` once the old styling impl is gone
|
|
|
|
newClasses: TStylingContext|null;
|
2018-01-09 18:38:17 -08:00
|
|
|
}
|
|
|
|
|
2018-10-12 18:49:00 -07:00
|
|
|
/** Static data for an element */
|
2018-05-24 13:13:51 -07:00
|
|
|
export interface TElementNode extends TNode {
|
2018-05-29 15:08:30 -07:00
|
|
|
/** Index in the data[] array */
|
|
|
|
index: number;
|
2018-09-13 16:07:23 -07:00
|
|
|
child: TElementNode|TTextNode|TElementContainerNode|TContainerNode|TProjectionNode|null;
|
2018-05-29 15:08:30 -07:00
|
|
|
/**
|
|
|
|
* Element nodes will have parents unless they are the first node of a component or
|
|
|
|
* embedded view (which means their parent is in a different view and must be
|
2018-09-13 16:07:23 -07:00
|
|
|
* retrieved using viewData[HOST_NODE]).
|
2018-05-29 15:08:30 -07:00
|
|
|
*/
|
2018-09-13 16:07:23 -07:00
|
|
|
parent: TElementNode|TElementContainerNode|null;
|
2018-05-24 13:13:51 -07:00
|
|
|
tViews: null;
|
2018-07-03 20:04:36 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* If this is a component TNode with projection, this will be an array of projected
|
2019-01-21 14:55:37 +01:00
|
|
|
* TNodes or native nodes (see TNode.projection for more info). If it's a regular element node or
|
|
|
|
* a component without projection, it will be null.
|
2018-07-03 20:04:36 -07:00
|
|
|
*/
|
2019-01-21 14:55:37 +01:00
|
|
|
projection: (TNode|RNode[])[]|null;
|
2018-05-24 13:13:51 -07:00
|
|
|
}
|
|
|
|
|
2018-10-12 18:49:00 -07:00
|
|
|
/** Static data for a text node */
|
2018-05-24 13:13:51 -07:00
|
|
|
export interface TTextNode extends TNode {
|
2018-05-29 15:08:30 -07:00
|
|
|
/** Index in the data[] array */
|
|
|
|
index: number;
|
2018-05-24 13:13:51 -07:00
|
|
|
child: null;
|
2018-05-29 15:08:30 -07:00
|
|
|
/**
|
|
|
|
* Text nodes will have parents unless they are the first node of a component or
|
|
|
|
* embedded view (which means their parent is in a different view and must be
|
|
|
|
* retrieved using LView.node).
|
|
|
|
*/
|
2018-09-13 16:07:23 -07:00
|
|
|
parent: TElementNode|TElementContainerNode|null;
|
2018-05-24 13:13:51 -07:00
|
|
|
tViews: null;
|
2018-07-03 20:04:36 -07:00
|
|
|
projection: null;
|
2018-05-24 13:13:51 -07:00
|
|
|
}
|
2018-01-09 18:38:17 -08:00
|
|
|
|
2018-10-12 18:49:00 -07:00
|
|
|
/** Static data for an LContainer */
|
2018-05-24 13:13:51 -07:00
|
|
|
export interface TContainerNode extends TNode {
|
2018-05-29 15:08:30 -07:00
|
|
|
/**
|
2018-06-01 14:46:28 -07:00
|
|
|
* Index in the data[] array.
|
2018-05-29 15:08:30 -07:00
|
|
|
*
|
2018-06-01 14:46:28 -07:00
|
|
|
* If it's -1, this is a dynamically created container node that isn't stored in
|
2018-05-29 15:08:30 -07:00
|
|
|
* data[] (e.g. when you inject ViewContainerRef) .
|
|
|
|
*/
|
2018-06-01 14:46:28 -07:00
|
|
|
index: number;
|
2018-05-24 13:13:51 -07:00
|
|
|
child: null;
|
2018-05-29 15:08:30 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Container nodes will have parents unless:
|
|
|
|
*
|
|
|
|
* - They are the first node of a component or embedded view
|
|
|
|
* - They are dynamically created
|
|
|
|
*/
|
2018-09-13 16:07:23 -07:00
|
|
|
parent: TElementNode|TElementContainerNode|null;
|
2018-05-24 13:13:51 -07:00
|
|
|
tViews: TView|TView[]|null;
|
2018-07-03 20:04:36 -07:00
|
|
|
projection: null;
|
2018-05-24 13:13:51 -07:00
|
|
|
}
|
|
|
|
|
2018-10-12 18:49:00 -07:00
|
|
|
/** Static data for an <ng-container> */
|
2018-09-13 16:07:23 -07:00
|
|
|
export interface TElementContainerNode extends TNode {
|
2018-11-21 21:14:06 -08:00
|
|
|
/** Index in the LView[] array. */
|
2018-09-13 16:07:23 -07:00
|
|
|
index: number;
|
|
|
|
child: TElementNode|TTextNode|TContainerNode|TElementContainerNode|TProjectionNode|null;
|
|
|
|
parent: TElementNode|TElementContainerNode|null;
|
|
|
|
tViews: null;
|
|
|
|
projection: null;
|
|
|
|
}
|
|
|
|
|
2018-11-13 09:36:30 +01:00
|
|
|
/** Static data for an ICU expression */
|
|
|
|
export interface TIcuContainerNode extends TNode {
|
2018-11-21 21:14:06 -08:00
|
|
|
/** Index in the LView[] array. */
|
2018-11-13 09:36:30 +01:00
|
|
|
index: number;
|
|
|
|
child: TElementNode|TTextNode|null;
|
|
|
|
parent: TElementNode|TElementContainerNode|null;
|
|
|
|
tViews: null;
|
|
|
|
projection: null;
|
|
|
|
/**
|
|
|
|
* Indicates the current active case for an ICU expression.
|
|
|
|
* It is null when there is no active case.
|
|
|
|
*/
|
|
|
|
activeCaseIndex: number|null;
|
|
|
|
}
|
|
|
|
|
2018-10-12 18:49:00 -07:00
|
|
|
/** Static data for a view */
|
2018-05-24 13:13:51 -07:00
|
|
|
export interface TViewNode extends TNode {
|
2018-06-01 14:46:28 -07:00
|
|
|
/** If -1, it's a dynamically created view. Otherwise, it is the view block ID. */
|
|
|
|
index: number;
|
2018-09-13 16:07:23 -07:00
|
|
|
child: TElementNode|TTextNode|TElementContainerNode|TContainerNode|TProjectionNode|null;
|
2018-05-29 15:08:30 -07:00
|
|
|
parent: TContainerNode|null;
|
2018-05-24 13:13:51 -07:00
|
|
|
tViews: null;
|
2018-07-03 20:04:36 -07:00
|
|
|
projection: null;
|
2018-05-24 13:13:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Static data for an LProjectionNode */
|
|
|
|
export interface TProjectionNode extends TNode {
|
2018-05-29 15:08:30 -07:00
|
|
|
/** Index in the data[] array */
|
2018-05-24 13:13:51 -07:00
|
|
|
child: null;
|
2018-05-29 15:08:30 -07:00
|
|
|
/**
|
|
|
|
* Projection nodes will have parents unless they are the first node of a component
|
|
|
|
* or embedded view (which means their parent is in a different view and must be
|
|
|
|
* retrieved using LView.node).
|
|
|
|
*/
|
2018-09-13 16:07:23 -07:00
|
|
|
parent: TElementNode|TElementContainerNode|null;
|
2018-05-24 13:13:51 -07:00
|
|
|
tViews: null;
|
2018-07-03 20:04:36 -07:00
|
|
|
|
|
|
|
/** Index of the projection node. (See TNode.projection for more info.) */
|
|
|
|
projection: number;
|
2018-05-24 13:13:51 -07:00
|
|
|
}
|
2018-01-09 18:38:17 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This mapping is necessary so we can set input properties and output listeners
|
|
|
|
* properly at runtime when property names are minified or aliased.
|
|
|
|
*
|
|
|
|
* Key: unminified / public input or output name
|
|
|
|
* Value: array containing minified / internal name and related directive index
|
|
|
|
*
|
|
|
|
* The value must be an array to support inputs and outputs with the same name
|
|
|
|
* on the same node.
|
|
|
|
*/
|
|
|
|
export type PropertyAliases = {
|
|
|
|
// This uses an object map because using the Map type would be too slow
|
|
|
|
[key: string]: PropertyAliasValue
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2018-02-07 22:19:24 -08:00
|
|
|
* Store the runtime input or output names for all the directives.
|
2018-01-09 18:38:17 -08:00
|
|
|
*
|
2019-01-16 09:35:35 -08:00
|
|
|
* i+0: directive instance index
|
|
|
|
* i+1: publicName
|
|
|
|
* i+2: privateName
|
2018-01-09 18:38:17 -08:00
|
|
|
*
|
2019-01-16 09:35:35 -08:00
|
|
|
* e.g. [0, 'change', 'change-minified']
|
2018-01-09 18:38:17 -08:00
|
|
|
*/
|
|
|
|
export type PropertyAliasValue = (number | string)[];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This array contains information about input properties that
|
|
|
|
* need to be set once from attribute data. It's ordered by
|
|
|
|
* directive index (relative to element) so it's simple to
|
|
|
|
* look up a specific directive's initial input data.
|
|
|
|
*
|
|
|
|
* Within each sub-array:
|
|
|
|
*
|
2019-01-16 09:35:35 -08:00
|
|
|
* i+0: attribute name
|
|
|
|
* i+1: minified/internal input name
|
|
|
|
* i+2: initial value
|
2018-01-09 18:38:17 -08:00
|
|
|
*
|
|
|
|
* If a directive on a node does not have any input properties
|
|
|
|
* that should be set from attributes, its index is set to null
|
|
|
|
* to avoid a sparse array.
|
|
|
|
*
|
2019-01-16 09:35:35 -08:00
|
|
|
* e.g. [null, ['role-min', 'minified-input', 'button']]
|
2018-01-09 18:38:17 -08:00
|
|
|
*/
|
|
|
|
export type InitialInputData = (InitialInputs | null)[];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Used by InitialInputData to store input properties
|
|
|
|
* that should be set once from attributes.
|
|
|
|
*
|
2019-01-16 09:35:35 -08:00
|
|
|
* i+0: attribute name
|
|
|
|
* i+1: minified/internal input name
|
|
|
|
* i+2: initial value
|
2018-01-09 18:38:17 -08:00
|
|
|
*
|
2019-01-16 09:35:35 -08:00
|
|
|
* e.g. ['role-min', 'minified-input', 'button']
|
2018-01-09 18:38:17 -08:00
|
|
|
*/
|
|
|
|
export type InitialInputs = string[];
|
|
|
|
|
|
|
|
// Note: This hack is necessary so we don't erroneously get a circular dependency
|
|
|
|
// failure based on types.
|
|
|
|
export const unusedValueExportToPlacateAjd = 1;
|
2018-08-14 16:25:01 +02:00
|
|
|
|
|
|
|
/**
|
2018-09-17 14:32:45 -07:00
|
|
|
* Type representing a set of TNodes that can have local refs (`#foo`) placed on them.
|
2018-08-14 16:25:01 +02:00
|
|
|
*/
|
2018-09-17 14:32:45 -07:00
|
|
|
export type TNodeWithLocalRefs = TContainerNode | TElementNode | TElementContainerNode;
|
2018-08-14 16:25:01 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Type for a function that extracts a value for a local refs.
|
|
|
|
* Example:
|
|
|
|
* - `<div #nativeDivEl>` - `nativeDivEl` should point to the native `<div>` element;
|
|
|
|
* - `<ng-template #tplRef>` - `tplRef` should point to the `TemplateRef` instance;
|
|
|
|
*/
|
2018-11-21 21:14:06 -08:00
|
|
|
export type LocalRefExtractor = (tNode: TNodeWithLocalRefs, currentView: LView) => any;
|