parent
b462f49ce7
commit
83b27bac17
@ -7,12 +7,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {ComponentRef, EmbeddedViewRef, Injector} from '../core';
|
import {ComponentRef, EmbeddedViewRef, Injector} from '../core';
|
||||||
|
|
||||||
import {assertNotNull} from './assert';
|
import {assertNotNull} from './assert';
|
||||||
import {NG_HOST_SYMBOL, createError, createViewState, directiveCreate, elementHost, enterView, leaveView} from './instructions';
|
import {NG_HOST_SYMBOL, createError, createViewState, directiveCreate, elementHost, enterView, leaveView} from './instructions';
|
||||||
import {LElement} from './l_node';
|
import {LElement} from './l_node';
|
||||||
import {ComponentDef, ComponentType} from './public_interfaces';
|
import {ComponentDef, ComponentType} from './public_interfaces';
|
||||||
import {RElement, Renderer3, RendererFactory3} from './renderer';
|
import {RElement, Renderer3, RendererFactory3} from './renderer';
|
||||||
import {stringify, notImplemented} from './util';
|
import {notImplemented, stringify} from './util';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,14 +9,17 @@
|
|||||||
// We are temporarily importing the existing viewEngine from core so we can be sure we are
|
// We are temporarily importing the existing viewEngine from core so we can be sure we are
|
||||||
// correctly implementing its interfaces for backwards compatibility.
|
// correctly implementing its interfaces for backwards compatibility.
|
||||||
import * as viewEngine from '../core';
|
import * as viewEngine from '../core';
|
||||||
|
|
||||||
import {BLOOM_SIZE, NG_ELEMENT_ID, getOrCreateNodeInjector} from './instructions';
|
import {BLOOM_SIZE, NG_ELEMENT_ID, getOrCreateNodeInjector} from './instructions';
|
||||||
import {LContainer, LNodeFlags, LNodeInjector} from './l_node';
|
import {LContainer, LNodeFlags, LNodeInjector} from './l_node';
|
||||||
import {ComponentTemplate, DirectiveDef} from './public_interfaces';
|
import {ComponentTemplate, DirectiveDef} from './public_interfaces';
|
||||||
import {stringify, notImplemented} from './util';
|
import {notImplemented, stringify} from './util';
|
||||||
|
|
||||||
|
|
||||||
/** Injection flags for DI. */
|
/** Injection flags for DI. */
|
||||||
export const enum InjectFlags {
|
export const enum InjectFlags {
|
||||||
/** Dependency is not required. Null will be injected if there is no provider for the dependency. */
|
/** Dependency is not required. Null will be injected if there is no provider for the dependency.
|
||||||
|
*/
|
||||||
Optional = 1 << 0,
|
Optional = 1 << 0,
|
||||||
/** When resolving a dependency, include the node that is requesting injection. */
|
/** When resolving a dependency, include the node that is requesting injection. */
|
||||||
CheckSelf = 1 << 1,
|
CheckSelf = 1 << 1,
|
||||||
@ -86,7 +89,9 @@ export function inject<T>(token: viewEngine.Type<T>, flags?: InjectFlags): T {
|
|||||||
|
|
||||||
// If no injector is found, we *know* that there is no ancestor injector that contains the
|
// If no injector is found, we *know* that there is no ancestor injector that contains the
|
||||||
// token, so we abort.
|
// token, so we abort.
|
||||||
if (!injector) { break; }
|
if (!injector) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// At this point, we have an injector which *may* contain the token, so we step through the
|
// At this point, we have an injector which *may* contain the token, so we step through the
|
||||||
// directives associated with the injector's corresponding node to get the directive instance.
|
// directives associated with the injector's corresponding node to get the directive instance.
|
||||||
@ -160,8 +165,8 @@ function bloomHashBit(type: viewEngine.Type<any>): number|null {
|
|||||||
* @param bloomBit The bit to check in each injector's bloom filter
|
* @param bloomBit The bit to check in each injector's bloom filter
|
||||||
* @returns An injector that might have the directive
|
* @returns An injector that might have the directive
|
||||||
*/
|
*/
|
||||||
export function bloomFindPossibleInjector(startInjector: LNodeInjector, bloomBit: number): LNodeInjector|
|
export function bloomFindPossibleInjector(
|
||||||
null {
|
startInjector: LNodeInjector, bloomBit: number): LNodeInjector|null {
|
||||||
// Create a mask that targets the specific bit associated with the directive we're looking for.
|
// Create a mask that targets the specific bit associated with the directive we're looking for.
|
||||||
// This will be a number between 0 and 31, corresponding to a bit position in a 32 bit integer.
|
// This will be a number between 0 and 31, corresponding to a bit position in a 32 bit integer.
|
||||||
const mask = 1 << bloomBit;
|
const mask = 1 << bloomBit;
|
||||||
@ -173,8 +178,8 @@ export function bloomFindPossibleInjector(startInjector: LNodeInjector, bloomBit
|
|||||||
// Our bloom filter size is 128 bits, which is four 32-bit bloom filter buckets:
|
// Our bloom filter size is 128 bits, which is four 32-bit bloom filter buckets:
|
||||||
// bf0 = [0 - 31], bf1 = [32 - 63], bf2 = [64 - 95], bf3 = [96 - 127]
|
// bf0 = [0 - 31], bf1 = [32 - 63], bf2 = [64 - 95], bf3 = [96 - 127]
|
||||||
// Get the bloom filter value from the appropriate bucket based on the directive's bloomBit.
|
// Get the bloom filter value from the appropriate bucket based on the directive's bloomBit.
|
||||||
let value: number =
|
let value: number = bloomBit < 64 ? (bloomBit < 32 ? injector.bf0 : injector.bf1) :
|
||||||
bloomBit < 64 ? (bloomBit < 32 ? injector.bf0 : injector.bf1) : (bloomBit < 96 ? injector.bf2 : injector.bf3);
|
(bloomBit < 96 ? injector.bf2 : injector.bf3);
|
||||||
|
|
||||||
// If the bloom filter value has the bit corresponding to the directive's bloomBit flipped on,
|
// If the bloom filter value has the bit corresponding to the directive's bloomBit flipped on,
|
||||||
// this injector is a potential match.
|
// this injector is a potential match.
|
||||||
@ -184,8 +189,8 @@ export function bloomFindPossibleInjector(startInjector: LNodeInjector, bloomBit
|
|||||||
|
|
||||||
// If the current injector does not have the directive, check the bloom filters for the ancestor
|
// If the current injector does not have the directive, check the bloom filters for the ancestor
|
||||||
// injectors (cbf0 - cbf3). These filters capture *all* ancestor injectors.
|
// injectors (cbf0 - cbf3). These filters capture *all* ancestor injectors.
|
||||||
value =
|
value = bloomBit < 64 ? (bloomBit < 32 ? injector.cbf0 : injector.cbf1) :
|
||||||
bloomBit < 64 ? (bloomBit < 32 ? injector.cbf0 : injector.cbf1) : (bloomBit < 96 ? injector.cbf2 : injector.cbf3);
|
(bloomBit < 96 ? injector.cbf2 : injector.cbf3);
|
||||||
|
|
||||||
// If the ancestor bloom filter value has the bit corresponding to the directive, traverse up to
|
// If the ancestor bloom filter value has the bit corresponding to the directive, traverse up to
|
||||||
// find the specific injector. If the ancestor bloom filter does not have the bit, we can abort.
|
// find the specific injector. If the ancestor bloom filter does not have the bit, we can abort.
|
||||||
@ -264,8 +269,8 @@ class ViewContainerRef implements viewEngine.ViewContainerRef {
|
|||||||
get(index: number): viewEngine.ViewRef|null { throw notImplemented(); }
|
get(index: number): viewEngine.ViewRef|null { throw notImplemented(); }
|
||||||
length: number;
|
length: number;
|
||||||
createEmbeddedView<C>(
|
createEmbeddedView<C>(
|
||||||
templateRef: viewEngine.TemplateRef<C>, context?: C|undefined,
|
templateRef: viewEngine.TemplateRef<C>, context?: C|undefined,
|
||||||
index?: number|undefined): viewEngine.EmbeddedViewRef<C> {
|
index?: number|undefined): viewEngine.EmbeddedViewRef<C> {
|
||||||
throw notImplemented();
|
throw notImplemented();
|
||||||
}
|
}
|
||||||
createComponent<C>(
|
createComponent<C>(
|
||||||
@ -274,8 +279,12 @@ class ViewContainerRef implements viewEngine.ViewContainerRef {
|
|||||||
ngModule?: viewEngine.NgModuleRef<any>|undefined): viewEngine.ComponentRef<C> {
|
ngModule?: viewEngine.NgModuleRef<any>|undefined): viewEngine.ComponentRef<C> {
|
||||||
throw notImplemented();
|
throw notImplemented();
|
||||||
}
|
}
|
||||||
insert(viewRef: viewEngine.ViewRef, index?: number|undefined): viewEngine.ViewRef { throw notImplemented(); }
|
insert(viewRef: viewEngine.ViewRef, index?: number|undefined): viewEngine.ViewRef {
|
||||||
move(viewRef: viewEngine.ViewRef, currentIndex: number): viewEngine.ViewRef { throw notImplemented(); }
|
throw notImplemented();
|
||||||
|
}
|
||||||
|
move(viewRef: viewEngine.ViewRef, currentIndex: number): viewEngine.ViewRef {
|
||||||
|
throw notImplemented();
|
||||||
|
}
|
||||||
indexOf(viewRef: viewEngine.ViewRef): number { throw notImplemented(); }
|
indexOf(viewRef: viewEngine.ViewRef): number { throw notImplemented(); }
|
||||||
remove(index?: number|undefined): void { throw notImplemented(); }
|
remove(index?: number|undefined): void { throw notImplemented(); }
|
||||||
detach(index?: number|undefined): viewEngine.ViewRef|null { throw notImplemented(); }
|
detach(index?: number|undefined): viewEngine.ViewRef|null { throw notImplemented(); }
|
||||||
|
@ -9,9 +9,11 @@
|
|||||||
import './ng_dev_mode';
|
import './ng_dev_mode';
|
||||||
|
|
||||||
import {Type} from '../core';
|
import {Type} from '../core';
|
||||||
|
|
||||||
import {assertEqual, assertLessThan, assertNotEqual, assertNotNull} from './assert';
|
import {assertEqual, assertLessThan, assertNotEqual, assertNotNull} from './assert';
|
||||||
import {CssSelector, ContainerState, ProjectionState, QueryState, ViewState} from './interfaces';
|
import {ContainerState, CssSelector, ProjectionState, QueryState, ViewState} from './interfaces';
|
||||||
import {LText, LView, LElement, LNode, LNodeFlags, LNodeInjector, LContainer, LProjection} from './l_node';
|
import {LContainer, LElement, LNode, LNodeFlags, LNodeInjector, LProjection, LText, LView} from './l_node';
|
||||||
|
|
||||||
import {NgStaticData, LNodeStatic, LContainerStatic, InitialInputData, InitialInputs, PropertyAliases, PropertyAliasValue,} from './l_node_static';
|
import {NgStaticData, LNodeStatic, LContainerStatic, InitialInputData, InitialInputs, PropertyAliases, PropertyAliasValue,} from './l_node_static';
|
||||||
import {assertNodeType} from './node_assert';
|
import {assertNodeType} from './node_assert';
|
||||||
import {appendChild, insertChild, insertView, processProjectedNode, removeView} from './node_manipulation';
|
import {appendChild, insertChild, insertView, processProjectedNode, removeView} from './node_manipulation';
|
||||||
@ -129,7 +131,8 @@ export function enterView(newViewState: ViewState, host: LElement | LView | null
|
|||||||
|
|
||||||
export const leaveView: (newViewState: ViewState) => void = enterView as any;
|
export const leaveView: (newViewState: ViewState) => void = enterView as any;
|
||||||
|
|
||||||
export function createViewState(viewId: number, renderer: Renderer3, ngStaticData: NgStaticData): ViewState {
|
export function createViewState(
|
||||||
|
viewId: number, renderer: Renderer3, ngStaticData: NgStaticData): ViewState {
|
||||||
const newView = {
|
const newView = {
|
||||||
parent: currentView,
|
parent: currentView,
|
||||||
id: viewId, // -1 for component views
|
id: viewId, // -1 for component views
|
||||||
@ -336,7 +339,7 @@ export function elementCreate(
|
|||||||
} else {
|
} else {
|
||||||
native = renderer.createElement(name);
|
native = renderer.createElement(name);
|
||||||
|
|
||||||
let componentView: ViewState | null = null;
|
let componentView: ViewState|null = null;
|
||||||
if (isHostElement) {
|
if (isHostElement) {
|
||||||
const ngStaticData = getTemplateStatic((nameOrComponentDef as ComponentDef<any>).template);
|
const ngStaticData = getTemplateStatic((nameOrComponentDef as ComponentDef<any>).template);
|
||||||
componentView = addToViewTree(createViewState(-1, renderer, ngStaticData));
|
componentView = addToViewTree(createViewState(-1, renderer, ngStaticData));
|
||||||
@ -402,7 +405,8 @@ export function elementHost(elementOrSelector: RElement | string, def: Component
|
|||||||
throw createError('Host node is required:', elementOrSelector);
|
throw createError('Host node is required:', elementOrSelector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
createLNode(0, LNodeFlags.Element, rNode, createViewState(-1, renderer, getTemplateStatic(def.template)));
|
createLNode(
|
||||||
|
0, LNodeFlags.Element, rNode, createViewState(-1, renderer, getTemplateStatic(def.template)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -454,8 +458,7 @@ export function listenerCreate(
|
|||||||
function outputCreate(outputs: (number | string)[], listener: Function): void {
|
function outputCreate(outputs: (number | string)[], listener: Function): void {
|
||||||
for (let i = 0; i < outputs.length; i += 2) {
|
for (let i = 0; i < outputs.length; i += 2) {
|
||||||
ngDevMode && assertDataInRange(outputs[i] as number);
|
ngDevMode && assertDataInRange(outputs[i] as number);
|
||||||
const subscription =
|
const subscription = data[outputs[i] as number][outputs[i | 1]].subscribe(listener);
|
||||||
data[outputs[i] as number][outputs[i | 1]].subscribe(listener);
|
|
||||||
cleanup !.push(subscription.unsubscribe, subscription);
|
cleanup !.push(subscription.unsubscribe, subscription);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -570,7 +573,8 @@ function setInputsForProperty(inputs: (number | string)[], value: any): void {
|
|||||||
*
|
*
|
||||||
* @param index Index where data should be stored in ngStaticData
|
* @param index Index where data should be stored in ngStaticData
|
||||||
*/
|
*/
|
||||||
function generatePropertyAliases(flags: number, data: LNodeStatic, isInputData = false): LNodeStatic {
|
function generatePropertyAliases(
|
||||||
|
flags: number, data: LNodeStatic, isInputData = false): LNodeStatic {
|
||||||
const start = flags >> LNodeFlags.INDX_SHIFT;
|
const start = flags >> LNodeFlags.INDX_SHIFT;
|
||||||
const size = (flags & LNodeFlags.SIZE_MASK) >> LNodeFlags.SIZE_SHIFT;
|
const size = (flags & LNodeFlags.SIZE_MASK) >> LNodeFlags.SIZE_SHIFT;
|
||||||
|
|
||||||
@ -582,7 +586,7 @@ function generatePropertyAliases(flags: number, data: LNodeStatic, isInputData =
|
|||||||
if (propertyAliasMap.hasOwnProperty(publicName)) {
|
if (propertyAliasMap.hasOwnProperty(publicName)) {
|
||||||
const internalName = propertyAliasMap[publicName];
|
const internalName = propertyAliasMap[publicName];
|
||||||
const staticDirData: PropertyAliases = isInputData ? (data.inputs || (data.inputs = {})) :
|
const staticDirData: PropertyAliases = isInputData ? (data.inputs || (data.inputs = {})) :
|
||||||
(data.outputs || (data.outputs = {}));
|
(data.outputs || (data.outputs = {}));
|
||||||
const hasProperty: boolean = staticDirData.hasOwnProperty(publicName);
|
const hasProperty: boolean = staticDirData.hasOwnProperty(publicName);
|
||||||
hasProperty ? staticDirData[publicName].push(i, internalName) :
|
hasProperty ? staticDirData[publicName].push(i, internalName) :
|
||||||
(staticDirData[publicName] = [i, internalName]);
|
(staticDirData[publicName] = [i, internalName]);
|
||||||
@ -938,8 +942,8 @@ export function viewCreate(viewBlockId: number): boolean {
|
|||||||
const containerState = container.data;
|
const containerState = container.data;
|
||||||
const views = containerState.views;
|
const views = containerState.views;
|
||||||
|
|
||||||
const existingView: LView|false = !creationMode && containerState.nextIndex < views.length &&
|
const existingView: LView|false =
|
||||||
views[containerState.nextIndex];
|
!creationMode && containerState.nextIndex < views.length && views[containerState.nextIndex];
|
||||||
let viewUpdateMode = existingView && viewBlockId === (existingView as LView).data.id;
|
let viewUpdateMode = existingView && viewBlockId === (existingView as LView).data.id;
|
||||||
|
|
||||||
if (viewUpdateMode) {
|
if (viewUpdateMode) {
|
||||||
@ -949,7 +953,8 @@ export function viewCreate(viewBlockId: number): boolean {
|
|||||||
enterView((existingView as LView).data, previousOrParentNode as LView);
|
enterView((existingView as LView).data, previousOrParentNode as LView);
|
||||||
} else {
|
} else {
|
||||||
// When we create a new View, we always reset the state of the instructions.
|
// When we create a new View, we always reset the state of the instructions.
|
||||||
const newViewState = createViewState(viewBlockId, renderer, initViewStaticData(viewBlockId, container));
|
const newViewState =
|
||||||
|
createViewState(viewBlockId, renderer, initViewStaticData(viewBlockId, container));
|
||||||
enterView(newViewState, createLNode(null, LNodeFlags.View, null, newViewState));
|
enterView(newViewState, createLNode(null, LNodeFlags.View, null, newViewState));
|
||||||
containerState.nextIndex++;
|
containerState.nextIndex++;
|
||||||
}
|
}
|
||||||
@ -1571,7 +1576,7 @@ function valueInData<T>(data: any[], index: number, value?: T): T {
|
|||||||
// We don't store any static data for local variables, so the first time
|
// We don't store any static data for local variables, so the first time
|
||||||
// we see the template, we should store as null to avoid a sparse array
|
// we see the template, we should store as null to avoid a sparse array
|
||||||
if (index >= ngStaticData.length) {
|
if (index >= ngStaticData.length) {
|
||||||
ngStaticData[index] = null;
|
ngStaticData[index] = null;
|
||||||
}
|
}
|
||||||
data[index] = value;
|
data[index] = value;
|
||||||
}
|
}
|
||||||
@ -1600,4 +1605,3 @@ function assertDataInRange(index: number, arr?: any[]) {
|
|||||||
if (arr == null) arr = data;
|
if (arr == null) arr = data;
|
||||||
assertLessThan(arr ? arr.length : 0, index, 'data.length');
|
assertLessThan(arr ? arr.length : 0, index, 'data.length');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,10 +7,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {QueryList, Type} from '../core';
|
import {QueryList, Type} from '../core';
|
||||||
|
|
||||||
|
import {LContainer, LElement, LNode, LText, LView} from './l_node';
|
||||||
|
import {LNodeStatic} from './l_node_static';
|
||||||
import {ComponentTemplate, DirectiveDef} from './public_interfaces';
|
import {ComponentTemplate, DirectiveDef} from './public_interfaces';
|
||||||
import {Renderer3} from './renderer';
|
import {Renderer3} from './renderer';
|
||||||
import {LNode, LView, LElement, LContainer, LText} from './l_node';
|
|
||||||
import {LNodeStatic} from './l_node_static';
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
const ngDevMode: boolean;
|
const ngDevMode: boolean;
|
||||||
|
@ -7,9 +7,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {ElementRef, Injector, TemplateRef, ViewContainerRef} from '../core';
|
import {ElementRef, Injector, TemplateRef, ViewContainerRef} from '../core';
|
||||||
import {RComment, RElement, RText} from './renderer';
|
|
||||||
import {ViewState, ContainerState, ProjectionState, QueryState} from './interfaces';
|
import {ContainerState, ProjectionState, QueryState, ViewState} from './interfaces';
|
||||||
import {LNodeStatic} from './l_node_static';
|
import {LNodeStatic} from './l_node_static';
|
||||||
|
import {RComment, RElement, RText} from './renderer';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LNodeFlags corresponds to the LNode.flags property. It contains information
|
* LNodeFlags corresponds to the LNode.flags property. It contains information
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
import {DirectiveDef} from './public_interfaces';
|
import {DirectiveDef} from './public_interfaces';
|
||||||
|
|
||||||
/** The type of the global ngStaticData array. */
|
/** The type of the global ngStaticData array. */
|
||||||
export type NgStaticData = (LNodeStatic | DirectiveDef<any> | null)[];
|
export type NgStaticData = (LNodeStatic | DirectiveDef<any>| null)[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LNode binding data (flywiehgt) for a particular node that is shared between all templates
|
* LNode binding data (flywiehgt) for a particular node that is shared between all templates
|
||||||
|
@ -6,11 +6,13 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as viewEngine from '../core';
|
import {DirectiveDef} from '@angular/core/src/render3/public_interfaces';
|
||||||
import {Observable} from 'rxjs/Observable';
|
import {Observable} from 'rxjs/Observable';
|
||||||
|
|
||||||
|
import * as viewEngine from '../core';
|
||||||
|
|
||||||
import {assertNotNull} from './assert';
|
import {assertNotNull} from './assert';
|
||||||
import {QueryState} from './interfaces';
|
import {QueryState} from './interfaces';
|
||||||
import {DirectiveDef} from '@angular/core/src/render3/public_interfaces';
|
|
||||||
import {LContainer, LNode, LNodeFlags, LView} from './l_node';
|
import {LContainer, LNode, LNodeFlags, LView} from './l_node';
|
||||||
|
|
||||||
|
|
||||||
@ -60,7 +62,9 @@ export class QueryState_ implements QueryState {
|
|||||||
|
|
||||||
constructor(deep?: QueryPredicate<any>) { this.deep = deep == null ? null : deep; }
|
constructor(deep?: QueryPredicate<any>) { this.deep = deep == null ? null : deep; }
|
||||||
|
|
||||||
track<T>(queryList: viewEngine.QueryList<T>, predicate: viewEngine.Type<T>|any[], descend?: boolean): void {
|
track<T>(
|
||||||
|
queryList: viewEngine.QueryList<T>, predicate: viewEngine.Type<T>|any[],
|
||||||
|
descend?: boolean): void {
|
||||||
// TODO(misko): This is not right. In case of inherited state, a calling track will incorrectly
|
// TODO(misko): This is not right. In case of inherited state, a calling track will incorrectly
|
||||||
// mutate parent.
|
// mutate parent.
|
||||||
if (descend) {
|
if (descend) {
|
||||||
|
@ -37,7 +37,8 @@ export function resetDOM() {
|
|||||||
requestAnimationFrame.queue = [];
|
requestAnimationFrame.queue = [];
|
||||||
containerEl = document.createElement('div');
|
containerEl = document.createElement('div');
|
||||||
containerEl.setAttribute('host', '');
|
containerEl.setAttribute('host', '');
|
||||||
host = createLNode(null, LNodeFlags.Element, containerEl, createViewState(-1, activeRenderer, null !));
|
host = createLNode(
|
||||||
|
null, LNodeFlags.Element, containerEl, createViewState(-1, activeRenderer, null !));
|
||||||
// TODO: assert that the global state is clean (e.g. ngData, previousOrParentNode, etc)
|
// TODO: assert that the global state is clean (e.g. ngData, previousOrParentNode, etc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user