refactor(ivy): LContainer now stored in LView[PARENT] (#28382)
- Removes CONTAINER_INDEX - LView[PARENT] now contains LContainer when necessary - Removes now unused arguments to methods after refactor PR Close #28382
This commit is contained in:
parent
f0f81f482e
commit
ba6aa93aa3
@ -11,6 +11,7 @@ import {assertDefined, assertEqual, throwError} from '../util/assert';
|
||||
import {getComponentDef, getNgModuleDef} from './definition';
|
||||
import {TNode} from './interfaces/node';
|
||||
import {LView} from './interfaces/view';
|
||||
import {isLContainer, isLView} from './util';
|
||||
|
||||
|
||||
export function assertComponentType(
|
||||
@ -44,3 +45,21 @@ export function assertDataNext(lView: LView, index: number, arr?: any[]) {
|
||||
assertEqual(
|
||||
arr.length, index, `index ${index} expected to be at the end of arr (length ${arr.length})`);
|
||||
}
|
||||
|
||||
export function assertLContainerOrUndefined(value: any): void {
|
||||
value && assertEqual(isLContainer(value), true, 'Expecting LContainer or undefined or null');
|
||||
}
|
||||
|
||||
export function assertLContainer(value: any): void {
|
||||
assertDefined(value, 'LContainer must be defined');
|
||||
assertEqual(isLContainer(value), true, 'Expecting LContainer');
|
||||
}
|
||||
|
||||
export function assertLViewOrUndefined(value: any): void {
|
||||
value && assertEqual(isLView(value), true, 'Expecting LView or undefined or null');
|
||||
}
|
||||
|
||||
export function assertLView(value: any) {
|
||||
assertDefined(value, 'LView must be defined');
|
||||
assertEqual(isLView(value), true, 'Expecting LView');
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ export function renderComponent<T>(
|
||||
component = createRootComponent(
|
||||
componentView, componentDef, rootView, rootContext, opts.hostFeatures || null);
|
||||
|
||||
addToViewTree(rootView, HEADER_OFFSET, componentView);
|
||||
addToViewTree(rootView, componentView);
|
||||
|
||||
refreshDescendantViews(rootView); // creation mode pass
|
||||
rootView[FLAGS] &= ~LViewFlags.CreationMode;
|
||||
|
@ -8,13 +8,14 @@
|
||||
|
||||
import {Injector} from '../di/injector';
|
||||
|
||||
import {assertLView} from './assert';
|
||||
import {discoverLocalRefs, getComponentAtNodeIndex, getDirectivesAtNodeIndex, getLContext} from './context_discovery';
|
||||
import {NodeInjector} from './di';
|
||||
import {LContext} from './interfaces/context';
|
||||
import {DirectiveDef} from './interfaces/definition';
|
||||
import {TElementNode, TNode, TNodeProviderIndexes} from './interfaces/node';
|
||||
import {CLEANUP, CONTEXT, FLAGS, HOST, LView, LViewFlags, PARENT, RootContext, TVIEW} from './interfaces/view';
|
||||
import {getRootView, readElementValue, renderStringify} from './util';
|
||||
import {CLEANUP, CONTEXT, FLAGS, HOST, LView, LViewFlags, TVIEW} from './interfaces/view';
|
||||
import {getLViewParent, getRootContext, readElementValue, renderStringify} from './util';
|
||||
|
||||
|
||||
|
||||
@ -95,28 +96,18 @@ export function getContext<T = {}>(element: Element): T|null {
|
||||
*/
|
||||
export function getViewComponent<T = {}>(element: Element | {}): T|null {
|
||||
const context = loadLContext(element) !;
|
||||
let lView: LView = context.lView;
|
||||
while (lView[PARENT] && lView[HOST] === null) {
|
||||
let lView = context.lView;
|
||||
let parent: LView|null;
|
||||
ngDevMode && assertLView(lView);
|
||||
while (lView[HOST] === null && (parent = getLViewParent(lView) !)) {
|
||||
// As long as lView[HOST] is null we know we are part of sub-template such as `*ngIf`
|
||||
lView = lView[PARENT] !;
|
||||
if (parent) {
|
||||
lView = parent;
|
||||
}
|
||||
}
|
||||
|
||||
return lView[FLAGS] & LViewFlags.IsRoot ? null : lView[CONTEXT] as T;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the `RootContext` instance that is associated with
|
||||
* the application where the target is situated.
|
||||
*
|
||||
*/
|
||||
export function getRootContext(target: LView | {}): RootContext {
|
||||
const lViewData = Array.isArray(target) ? target : loadLContext(target) !.lView;
|
||||
const rootLView = getRootView(lViewData);
|
||||
return rootLView[CONTEXT] as RootContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all root components.
|
||||
*
|
||||
|
@ -14,11 +14,11 @@ import {CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, SchemaMetadata} from '../metad
|
||||
import {validateAgainstEventAttributes, validateAgainstEventProperties} from '../sanitization/sanitization';
|
||||
import {Sanitizer} from '../sanitization/security';
|
||||
import {StyleSanitizeFn} from '../sanitization/style_sanitizer';
|
||||
import {assertDataInRange, assertDefined, assertEqual, assertLessThan, assertNotEqual} from '../util/assert';
|
||||
import {assertDataInRange, assertDefined, assertDomNode, assertEqual, assertLessThan, assertNotEqual} from '../util/assert';
|
||||
import {isObservable} from '../util/lang';
|
||||
import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../util/ng_reflect';
|
||||
|
||||
import {assertHasParent, assertPreviousIsParent} from './assert';
|
||||
import {assertHasParent, assertLContainerOrUndefined, assertLView, assertPreviousIsParent} from './assert';
|
||||
import {bindingUpdated, bindingUpdated2, bindingUpdated3, bindingUpdated4} from './bindings';
|
||||
import {attachPatchData, getComponentViewByInstance} from './context_discovery';
|
||||
import {diPublicInInjector, getNodeInjectable, getOrCreateInjectable, getOrCreateNodeInjectorForNode, injectAttributeImpl} from './di';
|
||||
@ -33,7 +33,8 @@ import {CssSelectorList, NG_PROJECT_AS_ATTR_NAME} from './interfaces/projection'
|
||||
import {LQueries} from './interfaces/query';
|
||||
import {GlobalTargetResolver, ProceduralRenderer3, RComment, RElement, RText, Renderer3, RendererFactory3, isProceduralRenderer} from './interfaces/renderer';
|
||||
import {SanitizerFn} from './interfaces/sanitization';
|
||||
import {BINDING_INDEX, CLEANUP, CONTAINER_INDEX, CONTEXT, DECLARATION_VIEW, ExpandoInstructions, FLAGS, HEADER_OFFSET, HOST, INJECTOR, InitPhaseState, LView, LViewFlags, NEXT, OpaqueViewState, PARENT, QUERIES, RENDERER, RENDERER_FACTORY, RootContext, RootContextFlags, SANITIZER, TAIL, TData, TVIEW, TView, T_HOST} from './interfaces/view';
|
||||
import {StylingContext} from './interfaces/styling';
|
||||
import {BINDING_INDEX, CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DECLARATION_VIEW, ExpandoInstructions, FLAGS, HEADER_OFFSET, HOST, INJECTOR, InitPhaseState, LView, LViewFlags, NEXT, OpaqueViewState, PARENT, QUERIES, RENDERER, RENDERER_FACTORY, RootContext, RootContextFlags, SANITIZER, TData, TVIEW, TView, T_HOST} from './interfaces/view';
|
||||
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
|
||||
import {appendChild, appendProjectedNode, createTextNode, getLViewChild, insertView, removeView} from './node_manipulation';
|
||||
import {isNodeMatchingSelectorList, matchingSelectorIndex} from './node_selector_matcher';
|
||||
@ -42,7 +43,7 @@ import {getInitialClassNameValue, getInitialStyleStringValue, initializeStaticCo
|
||||
import {BoundPlayerFactory} from './styling/player_factory';
|
||||
import {ANIMATION_PROP_PREFIX, allocateDirectiveIntoContext, createEmptyStylingContext, forceClassesAsString, forceStylesAsString, getStylingContext, hasClassInput, hasStyleInput, hasStyling, isAnimationProp} from './styling/util';
|
||||
import {NO_CHANGE} from './tokens';
|
||||
import {INTERPOLATION_DELIMITER, applyOnCreateInstructions, findComponentView, getComponentViewByIndex, getNativeByIndex, getNativeByTNode, getRootContext, getRootView, getTNode, isComponent, isComponentDef, isContentQueryHost, isRootView, loadInternal, readElementValue, readPatchedLView, renderStringify} from './util';
|
||||
import {INTERPOLATION_DELIMITER, applyOnCreateInstructions, findComponentView, getComponentViewByIndex, getLViewParent, getNativeByIndex, getNativeByTNode, getRootContext, getRootView, getTNode, isComponent, isComponentDef, isContentQueryHost, isRootView, loadInternal, readElementValue, readPatchedLView, renderStringify} from './util';
|
||||
|
||||
|
||||
|
||||
@ -816,7 +817,6 @@ function createViewBlueprint(bindingStartIndex: number, initialViewLength: numbe
|
||||
const blueprint = new Array(initialViewLength)
|
||||
.fill(null, 0, bindingStartIndex)
|
||||
.fill(NO_CHANGE, bindingStartIndex) as LView;
|
||||
blueprint[CONTAINER_INDEX] = -1;
|
||||
blueprint[BINDING_INDEX] = bindingStartIndex;
|
||||
return blueprint;
|
||||
}
|
||||
@ -2098,11 +2098,10 @@ function addComponentLogic<T>(
|
||||
// accessed through their containers because they may be removed / re-added later.
|
||||
const rendererFactory = lView[RENDERER_FACTORY];
|
||||
const componentView = addToViewTree(
|
||||
lView, previousOrParentTNode.index as number,
|
||||
createLView(
|
||||
lView, tView, null, def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways,
|
||||
lView[previousOrParentTNode.index], previousOrParentTNode as TElementNode,
|
||||
rendererFactory, lView[RENDERER_FACTORY].createRenderer(native as RElement, def)));
|
||||
lView, createLView(
|
||||
lView, tView, null, def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways,
|
||||
lView[previousOrParentTNode.index], previousOrParentTNode as TElementNode,
|
||||
rendererFactory, lView[RENDERER_FACTORY].createRenderer(native as RElement, def)));
|
||||
|
||||
componentView[T_HOST] = previousOrParentTNode as TElementNode;
|
||||
|
||||
@ -2208,8 +2207,10 @@ function generateInitialInputs(
|
||||
* @returns LContainer
|
||||
*/
|
||||
export function createLContainer(
|
||||
hostNative: RElement | RComment, currentView: LView, native: RComment,
|
||||
hostNative: RElement | RComment | StylingContext | LView, currentView: LView, native: RComment,
|
||||
isForViewContainerRef?: boolean): LContainer {
|
||||
ngDevMode && assertDomNode(native);
|
||||
ngDevMode && assertLView(currentView);
|
||||
return [
|
||||
isForViewContainerRef ? -1 : 0, // active index
|
||||
[], // views
|
||||
@ -2295,7 +2296,7 @@ function containerInternal(
|
||||
|
||||
// Containers are added to the current view tree instead of their embedded views
|
||||
// because views can be removed and re-inserted.
|
||||
addToViewTree(lView, index + HEADER_OFFSET, lContainer);
|
||||
addToViewTree(lView, lContainer);
|
||||
|
||||
ngDevMode && assertNodeType(getPreviousOrParentTNode(), TNodeType.Container);
|
||||
return tNode;
|
||||
@ -2457,7 +2458,7 @@ export function embeddedViewStart(viewBlockId: number, consts: number, vars: num
|
||||
if (lContainer) {
|
||||
if (isCreationMode(viewToRender)) {
|
||||
// it is a new view, insert it into collection of views for a given container
|
||||
insertView(viewToRender, lContainer, lView, lContainer[ACTIVE_INDEX] !, -1);
|
||||
insertView(viewToRender, lContainer, lContainer[ACTIVE_INDEX] !);
|
||||
}
|
||||
lContainer[ACTIVE_INDEX] !++;
|
||||
}
|
||||
@ -2502,7 +2503,9 @@ export function embeddedViewEnd(): void {
|
||||
lView[FLAGS] &= ~LViewFlags.CreationMode;
|
||||
}
|
||||
refreshDescendantViews(lView); // update mode pass
|
||||
leaveView(lView[PARENT] !);
|
||||
const lContainer = lView[PARENT] as LContainer;
|
||||
ngDevMode && assertLContainerOrUndefined(lContainer);
|
||||
leaveView(lContainer[PARENT] !);
|
||||
setPreviousOrParentTNode(viewHost !);
|
||||
setIsParent(false);
|
||||
}
|
||||
@ -2648,7 +2651,8 @@ export function projection(nodeIndex: number, selectorIndex: number = 0, attrs?:
|
||||
const componentView = findComponentView(lView);
|
||||
const componentNode = componentView[T_HOST] as TElementNode;
|
||||
let nodeToProject = (componentNode.projection as(TNode | null)[])[selectorIndex];
|
||||
let projectedView = componentView[PARENT] !;
|
||||
let projectedView = componentView[PARENT] !as LView;
|
||||
ngDevMode && assertLView(projectedView);
|
||||
let projectionNodeIndex = -1;
|
||||
|
||||
if (Array.isArray(nodeToProject)) {
|
||||
@ -2670,7 +2674,7 @@ export function projection(nodeIndex: number, selectorIndex: number = 0, attrs?:
|
||||
projectionNodeStack[++projectionNodeIndex] = projectedView;
|
||||
|
||||
nodeToProject = firstProjectedNode;
|
||||
projectedView = currentComponentView[PARENT] !;
|
||||
projectedView = getLViewParent(currentComponentView) !;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -2703,16 +2707,17 @@ export function projection(nodeIndex: number, selectorIndex: number = 0, attrs?:
|
||||
* @param state The LView or LContainer to add to the view tree
|
||||
* @returns The state passed in
|
||||
*/
|
||||
export function addToViewTree<T extends LView|LContainer>(
|
||||
lView: LView, adjustedHostIndex: number, state: T): T {
|
||||
const tView = lView[TVIEW];
|
||||
if (lView[TAIL]) {
|
||||
lView[TAIL] ![NEXT] = state;
|
||||
} else if (tView.firstTemplatePass) {
|
||||
tView.childIndex = adjustedHostIndex;
|
||||
export function addToViewTree<T extends LView|LContainer>(lView: LView, lViewOrLContainer: T): T {
|
||||
// TODO(benlesh/misko): This implementation is incorrect, because it always adds the LContainer to
|
||||
// the end of the queue, which means if the developer asks for the LContainers out of order, the
|
||||
// change detection will run out of order.
|
||||
if (lView[CHILD_HEAD]) {
|
||||
lView[CHILD_TAIL] ![NEXT] = lViewOrLContainer;
|
||||
} else {
|
||||
lView[CHILD_HEAD] = lViewOrLContainer;
|
||||
}
|
||||
lView[TAIL] = state;
|
||||
return state;
|
||||
lView[CHILD_TAIL] = lViewOrLContainer;
|
||||
return lViewOrLContainer;
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
@ -2721,6 +2726,7 @@ export function addToViewTree<T extends LView|LContainer>(
|
||||
|
||||
/** If node is an OnPush component, marks its LView dirty. */
|
||||
function markDirtyIfOnPush(lView: LView, viewIndex: number): void {
|
||||
ngDevMode && assertLView(lView);
|
||||
const childComponentLView = getComponentViewByIndex(viewIndex, lView);
|
||||
if (!(childComponentLView[FLAGS] & LViewFlags.CheckAlways)) {
|
||||
childComponentLView[FLAGS] |= LViewFlags.Dirty;
|
||||
@ -2780,12 +2786,13 @@ function wrapListener(
|
||||
export function markViewDirty(lView: LView): LView|null {
|
||||
while (lView) {
|
||||
lView[FLAGS] |= LViewFlags.Dirty;
|
||||
const parent = getLViewParent(lView);
|
||||
// Stop traversing up as soon as you find a root view that wasn't attached to any container
|
||||
if (isRootView(lView) && lView[CONTAINER_INDEX] === -1) {
|
||||
if (isRootView(lView) && !parent) {
|
||||
return lView;
|
||||
}
|
||||
// continue otherwise
|
||||
lView = lView[PARENT] !;
|
||||
lView = parent !;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ export interface LContainer extends Array<any> {
|
||||
* Access to the parent view is necessary so we can propagate back
|
||||
* up from inside a container to parent[NEXT].
|
||||
*/
|
||||
[PARENT]: LView|null;
|
||||
[PARENT]: LView;
|
||||
|
||||
/**
|
||||
* This allows us to jump from a container to a sibling container or component
|
||||
@ -85,10 +85,10 @@ export interface LContainer extends Array<any> {
|
||||
* It could also be a styling context if this is a node with a style/class
|
||||
* binding.
|
||||
*/
|
||||
[HOST]: RElement|RComment|StylingContext|LView;
|
||||
readonly[HOST]: RElement|RComment|StylingContext|LView;
|
||||
|
||||
/** The comment element that serves as an anchor for this LContainer. */
|
||||
[NATIVE]: RComment;
|
||||
readonly[NATIVE]: RComment;
|
||||
}
|
||||
|
||||
// Note: This hack is necessary so we don't erroneously get a circular dependency
|
||||
|
@ -110,11 +110,27 @@ export const domRendererFactory3: RendererFactory3 = {
|
||||
|
||||
/** Subset of API needed for appending elements and text nodes. */
|
||||
export interface RNode {
|
||||
/**
|
||||
* Returns the parent Element, Document, or DocumentFragment
|
||||
*/
|
||||
parentNode: RNode|null;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the parent Element if there is one
|
||||
*/
|
||||
parentElement: RElement|null;
|
||||
|
||||
/**
|
||||
* Gets the Node immediately following this one in the parent's childNodes
|
||||
*/
|
||||
nextSibling: RNode|null;
|
||||
|
||||
removeChild(oldChild: RNode): void;
|
||||
/**
|
||||
* Removes a child from the current node and returns the removed node
|
||||
* @param oldChild the child node to remove
|
||||
*/
|
||||
removeChild(oldChild: RNode): RNode;
|
||||
|
||||
/**
|
||||
* Insert a child node.
|
||||
|
@ -41,8 +41,8 @@ export const INJECTOR = 10;
|
||||
export const RENDERER_FACTORY = 11;
|
||||
export const RENDERER = 12;
|
||||
export const SANITIZER = 13;
|
||||
export const TAIL = 14;
|
||||
export const CONTAINER_INDEX = 15;
|
||||
export const CHILD_HEAD = 14;
|
||||
export const CHILD_TAIL = 15;
|
||||
export const CONTENT_QUERIES = 16;
|
||||
export const DECLARATION_VIEW = 17;
|
||||
/** Size of LView's header. Necessary to adjust for it when setting slots. */
|
||||
@ -86,7 +86,7 @@ export interface LView extends Array<any> {
|
||||
* This is the "insertion" view for embedded views. This allows us to properly
|
||||
* destroy embedded views.
|
||||
*/
|
||||
[PARENT]: LView|null;
|
||||
[PARENT]: LView|LContainer|null;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -168,17 +168,7 @@ export interface LView extends Array<any> {
|
||||
* The tail allows us to quickly add a new state to the end of the view list
|
||||
* without having to propagate starting from the first child.
|
||||
*/
|
||||
[TAIL]: LView|LContainer|null;
|
||||
|
||||
/**
|
||||
* The index of the parent container's host node. Applicable only to embedded views that
|
||||
* have been inserted dynamically. Will be -1 for component views and inline views.
|
||||
*
|
||||
* This is necessary to jump from dynamically created embedded views to their parent
|
||||
* containers because their parent cannot be stored on the TViewNode (views may be inserted
|
||||
* in multiple containers, so the parent cannot be shared between view instances).
|
||||
*/
|
||||
[CONTAINER_INDEX]: number;
|
||||
[CHILD_TAIL]: LView|LContainer|null;
|
||||
|
||||
/**
|
||||
* Stores QueryLists associated with content queries of a directive. This data structure is
|
||||
|
@ -7,29 +7,33 @@
|
||||
*/
|
||||
|
||||
import {ViewEncapsulation} from '../metadata/view';
|
||||
import {assertDefined} from '../util/assert';
|
||||
|
||||
import {assertLContainer, assertLView} from './assert';
|
||||
import {attachPatchData} from './context_discovery';
|
||||
import {LContainer, NATIVE, VIEWS, unusedValueExportToPlacateAjd as unused1} from './interfaces/container';
|
||||
import {ComponentDef} from './interfaces/definition';
|
||||
import {NodeInjectorFactory} from './interfaces/injector';
|
||||
import {TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, TViewNode, unusedValueExportToPlacateAjd as unused2} from './interfaces/node';
|
||||
import {TElementNode, TNode, TNodeFlags, TNodeType, TViewNode, unusedValueExportToPlacateAjd as unused2} from './interfaces/node';
|
||||
import {unusedValueExportToPlacateAjd as unused3} from './interfaces/projection';
|
||||
import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, isProceduralRenderer, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer';
|
||||
import {CLEANUP, CONTAINER_INDEX, FLAGS, HEADER_OFFSET, HookData, LView, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, TVIEW, T_HOST, unusedValueExportToPlacateAjd as unused5} from './interfaces/view';
|
||||
import {CHILD_HEAD, CLEANUP, FLAGS, HEADER_OFFSET, HookData, LView, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, TVIEW, T_HOST, unusedValueExportToPlacateAjd as unused5} from './interfaces/view';
|
||||
import {assertNodeType} from './node_assert';
|
||||
import {findComponentView, getNativeByTNode, isComponent, isLContainer, isRootView, readElementValue, renderStringify} from './util';
|
||||
import {findComponentView, getLViewParent, getNativeByTNode, isComponent, isLContainer, isLView, isRootView, readElementValue, renderStringify} from './util';
|
||||
|
||||
const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4 + unused5;
|
||||
|
||||
export function getLContainer(tNode: TViewNode, embeddedView: LView): LContainer|null {
|
||||
ngDevMode && assertLView(embeddedView);
|
||||
const container = embeddedView[PARENT] as LContainer;
|
||||
if (tNode.index === -1) {
|
||||
// This is a dynamically created view inside a dynamic container.
|
||||
// If the host index is -1, the view has not yet been inserted, so it has no parent.
|
||||
const containerHostIndex = embeddedView[CONTAINER_INDEX];
|
||||
return containerHostIndex > -1 ? embeddedView[PARENT] ![containerHostIndex] : null;
|
||||
// The parent isn't an LContainer if the embedded view hasn't been attached yet.
|
||||
return isLContainer(container) ? container : null;
|
||||
} else {
|
||||
ngDevMode && assertLContainer(container);
|
||||
// This is a inline view node (e.g. embeddedViewStart)
|
||||
return embeddedView[PARENT] ![tNode.parent !.index] as LContainer;
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,7 +127,7 @@ function walkTNodeTree(
|
||||
projectionNodeStack[++projectionNodeIndex] = tNode;
|
||||
projectionNodeStack[++projectionNodeIndex] = currentView !;
|
||||
if (head) {
|
||||
currentView = componentView[PARENT] !;
|
||||
currentView = componentView[PARENT] !as LView;
|
||||
nextTNode = currentView[TVIEW].data[head.index] as TNode;
|
||||
}
|
||||
}
|
||||
@ -156,7 +160,7 @@ function walkTNodeTree(
|
||||
|
||||
// When exiting a container, the beforeNode must be restored to the previous value
|
||||
if (tNode.type === TNodeType.Container) {
|
||||
currentView = currentView[PARENT] !;
|
||||
currentView = getLViewParent(currentView) !;
|
||||
beforeNode = currentView[tNode.index][NATIVE];
|
||||
}
|
||||
|
||||
@ -252,35 +256,35 @@ export function addRemoveViewFromContainer(
|
||||
*/
|
||||
export function destroyViewTree(rootView: LView): void {
|
||||
// If the view has no children, we can clean it up and return early.
|
||||
if (rootView[TVIEW].childIndex === -1) {
|
||||
let lViewOrLContainer = rootView[CHILD_HEAD];
|
||||
if (!lViewOrLContainer) {
|
||||
return cleanUpView(rootView);
|
||||
}
|
||||
let viewOrContainer: LView|LContainer|null = getLViewChild(rootView);
|
||||
|
||||
while (viewOrContainer) {
|
||||
while (lViewOrLContainer) {
|
||||
let next: LView|LContainer|null = null;
|
||||
|
||||
if (viewOrContainer.length >= HEADER_OFFSET) {
|
||||
if (isLView(lViewOrLContainer)) {
|
||||
// If LView, traverse down to child.
|
||||
const view = viewOrContainer as LView;
|
||||
if (view[TVIEW].childIndex > -1) next = getLViewChild(view);
|
||||
next = lViewOrLContainer[CHILD_HEAD];
|
||||
} else {
|
||||
ngDevMode && assertLContainer(lViewOrLContainer);
|
||||
// If container, traverse down to its first LView.
|
||||
const container = viewOrContainer as LContainer;
|
||||
if (container[VIEWS].length) next = container[VIEWS][0];
|
||||
const views = lViewOrLContainer[VIEWS] as LView[];
|
||||
if (views.length > 0) next = views[0];
|
||||
}
|
||||
|
||||
if (next == null) {
|
||||
if (!next) {
|
||||
// Only clean up view when moving to the side or up, as destroy hooks
|
||||
// should be called in order from the bottom up.
|
||||
while (viewOrContainer && !viewOrContainer ![NEXT] && viewOrContainer !== rootView) {
|
||||
cleanUpView(viewOrContainer);
|
||||
viewOrContainer = getParentState(viewOrContainer, rootView);
|
||||
while (lViewOrLContainer && !lViewOrLContainer ![NEXT] && lViewOrLContainer !== rootView) {
|
||||
cleanUpView(lViewOrLContainer);
|
||||
lViewOrLContainer = getParentState(lViewOrLContainer, rootView);
|
||||
}
|
||||
cleanUpView(viewOrContainer || rootView);
|
||||
next = viewOrContainer && viewOrContainer ![NEXT];
|
||||
cleanUpView(lViewOrLContainer || rootView);
|
||||
next = lViewOrLContainer && lViewOrLContainer ![NEXT];
|
||||
}
|
||||
viewOrContainer = next;
|
||||
lViewOrLContainer = next;
|
||||
}
|
||||
}
|
||||
|
||||
@ -294,15 +298,13 @@ export function destroyViewTree(rootView: LView): void {
|
||||
*
|
||||
* @param lView The view to insert
|
||||
* @param lContainer The container into which the view should be inserted
|
||||
* @param parentView The new parent of the inserted view
|
||||
* @param index The index at which to insert the view
|
||||
* @param containerIndex The index of the container node, if dynamic
|
||||
* @param index Which index in the container to insert the child view into
|
||||
*/
|
||||
export function insertView(
|
||||
lView: LView, lContainer: LContainer, parentView: LView, index: number,
|
||||
containerIndex: number) {
|
||||
export function insertView(lView: LView, lContainer: LContainer, index: number) {
|
||||
ngDevMode && assertLView(lView);
|
||||
ngDevMode && assertLContainer(lContainer);
|
||||
const views = lContainer[VIEWS];
|
||||
|
||||
ngDevMode && assertDefined(views, 'Container must have views');
|
||||
if (index > 0) {
|
||||
// This is a new view, we need to add it to the children.
|
||||
views[index - 1][NEXT] = lView;
|
||||
@ -316,12 +318,7 @@ export function insertView(
|
||||
lView[NEXT] = null;
|
||||
}
|
||||
|
||||
// Dynamically inserted views need a reference to their parent container's host so it's
|
||||
// possible to jump from a view to its container's next when walking the node tree.
|
||||
if (containerIndex > -1) {
|
||||
lView[CONTAINER_INDEX] = containerIndex;
|
||||
lView[PARENT] = parentView;
|
||||
}
|
||||
lView[PARENT] = lContainer;
|
||||
|
||||
// Notify query that a new view has been added
|
||||
if (lView[QUERIES]) {
|
||||
@ -354,7 +351,6 @@ export function detachView(lContainer: LContainer, removeIndex: number): LView {
|
||||
if (viewToDetach[QUERIES]) {
|
||||
viewToDetach[QUERIES] !.removeView();
|
||||
}
|
||||
viewToDetach[CONTAINER_INDEX] = -1;
|
||||
viewToDetach[PARENT] = null;
|
||||
// Unsets the attached flag
|
||||
viewToDetach[FLAGS] &= ~LViewFlags.Attached;
|
||||
@ -404,20 +400,21 @@ export function destroyLView(view: LView) {
|
||||
* embedded views, the container (which is the view node's parent, but not the
|
||||
* LView's parent) needs to be checked for a possible next property.
|
||||
*
|
||||
* @param state The LViewOrLContainer for which we need a parent state
|
||||
* @param lViewOrLContainer The LViewOrLContainer for which we need a parent state
|
||||
* @param rootView The rootView, so we don't propagate too far up the view tree
|
||||
* @returns The correct parent LViewOrLContainer
|
||||
*/
|
||||
export function getParentState(state: LView | LContainer, rootView: LView): LView|LContainer|null {
|
||||
export function getParentState(lViewOrLContainer: LView | LContainer, rootView: LView): LView|
|
||||
LContainer|null {
|
||||
let tNode;
|
||||
if (state.length >= HEADER_OFFSET && (tNode = (state as LView) ![T_HOST]) &&
|
||||
if (isLView(lViewOrLContainer) && (tNode = lViewOrLContainer[T_HOST]) &&
|
||||
tNode.type === TNodeType.View) {
|
||||
// if it's an embedded view, the state needs to go up to the container, in case the
|
||||
// container has a next
|
||||
return getLContainer(tNode as TViewNode, state as LView) as LContainer;
|
||||
return getLContainer(tNode as TViewNode, lViewOrLContainer);
|
||||
} else {
|
||||
// otherwise, use parent view for containers or component views
|
||||
return state[PARENT] === rootView ? null : state[PARENT];
|
||||
return lViewOrLContainer[PARENT] === rootView ? null : lViewOrLContainer[PARENT];
|
||||
}
|
||||
}
|
||||
|
||||
@ -576,9 +573,10 @@ function getRenderParent(tNode: TNode, currentView: LView): RElement|null {
|
||||
* a host element.
|
||||
*/
|
||||
function getHostNative(currentView: LView): RElement|null {
|
||||
ngDevMode && assertLView(currentView);
|
||||
const hostTNode = currentView[T_HOST];
|
||||
return hostTNode && hostTNode.type === TNodeType.Element ?
|
||||
(getNativeByTNode(hostTNode, currentView[PARENT] !) as RElement) :
|
||||
(getNativeByTNode(hostTNode, getLViewParent(currentView) !) as RElement) :
|
||||
null;
|
||||
}
|
||||
|
||||
|
@ -8,11 +8,11 @@
|
||||
import '../util/ng_dev_mode';
|
||||
|
||||
import {getLContext} from './context_discovery';
|
||||
import {getRootContext} from './discovery_utils';
|
||||
import {scheduleTick} from './instructions';
|
||||
import {ComponentInstance, DirectiveInstance, Player} from './interfaces/player';
|
||||
import {HEADER_OFFSET, RootContextFlags} from './interfaces/view';
|
||||
import {RootContextFlags} from './interfaces/view';
|
||||
import {addPlayerInternal, getOrCreatePlayerContext, getPlayerContext, getPlayersInternal, getStylingContext, throwInvalidRefError} from './styling/util';
|
||||
import {getRootContext} from './util';
|
||||
|
||||
/**
|
||||
* Adds a player to an element, directive or component instance that will later be
|
||||
|
@ -8,12 +8,14 @@
|
||||
|
||||
import {assertDefined} from '../util/assert';
|
||||
|
||||
import {assertLViewOrUndefined} from './assert';
|
||||
import {executeHooks} from './hooks';
|
||||
import {ComponentDef, DirectiveDef} from './interfaces/definition';
|
||||
import {TElementNode, TNode, TViewNode} from './interfaces/node';
|
||||
import {BINDING_INDEX, CONTEXT, DECLARATION_VIEW, FLAGS, InitPhaseState, LView, LViewFlags, OpaqueViewState, TVIEW} from './interfaces/view';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Store the element depth count. This is used to identify the root elements of the template
|
||||
* so that we can than attach `LView` to only those elements.
|
||||
@ -142,6 +144,7 @@ export function setPreviousOrParentTNode(tNode: TNode) {
|
||||
}
|
||||
|
||||
export function setTNodeAndViewData(tNode: TNode, view: LView) {
|
||||
ngDevMode && assertLViewOrUndefined(view);
|
||||
previousOrParentTNode = tNode;
|
||||
lView = view;
|
||||
}
|
||||
@ -249,6 +252,7 @@ export function setCurrentQueryIndex(value: number): void {
|
||||
* @returns the previous state;
|
||||
*/
|
||||
export function enterView(newView: LView, hostTNode: TElementNode | TViewNode | null): LView {
|
||||
ngDevMode && assertLViewOrUndefined(newView);
|
||||
const oldView = lView;
|
||||
if (newView) {
|
||||
const tView = newView[TVIEW];
|
||||
|
@ -9,17 +9,36 @@
|
||||
import {assertDataInRange, assertDefined, assertGreaterThan, assertLessThan} from '../util/assert';
|
||||
import {global} from '../util/global';
|
||||
|
||||
import {assertLView} from './assert';
|
||||
import {LCONTAINER_LENGTH, LContainer} from './interfaces/container';
|
||||
import {LContext, MONKEY_PATCH_KEY_NAME} from './interfaces/context';
|
||||
import {ComponentDef, DirectiveDef} from './interfaces/definition';
|
||||
import {NO_PARENT_INJECTOR, RelativeInjectorLocation, RelativeInjectorLocationFlags} from './interfaces/injector';
|
||||
import {TContainerNode, TElementNode, TNode, TNodeFlags, TNodeType} from './interfaces/node';
|
||||
import {RComment, RElement, RText} from './interfaces/renderer';
|
||||
import {StylingContext} from './interfaces/styling';
|
||||
import {CONTEXT, DECLARATION_VIEW, FLAGS, HEADER_OFFSET, HOST, LView, LViewFlags, PARENT, RootContext, TData, TVIEW, T_HOST} from './interfaces/view';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the parent LView of the passed LView, if the PARENT is an LContainer, will get the parent of
|
||||
* that LContainer, which is an LView
|
||||
* @param lView the lView whose parent to get
|
||||
*/
|
||||
export function getLViewParent(lView: LView): LView|null {
|
||||
ngDevMode && assertLView(lView);
|
||||
const parent = lView[PARENT];
|
||||
return isLContainer(parent) ? parent[PARENT] ! : parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the value is an {@link LView}
|
||||
* @param value the value to check
|
||||
*/
|
||||
export function isLView(value: any): value is LView {
|
||||
return Array.isArray(value) && value.length >= HEADER_OFFSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the values are different from a change detection stand point.
|
||||
*
|
||||
@ -85,7 +104,7 @@ export function loadInternal<T>(view: LView | TData, index: number): T {
|
||||
*
|
||||
* @param value The initial value in `LView`
|
||||
*/
|
||||
export function readElementValue(value: RElement | StylingContext | LContainer | LView): RElement {
|
||||
export function readElementValue(value: any): RElement {
|
||||
while (Array.isArray(value)) {
|
||||
value = value[HOST] as any;
|
||||
}
|
||||
@ -113,7 +132,9 @@ export function getTNode(index: number, view: LView): TNode {
|
||||
export function getComponentViewByIndex(nodeIndex: number, hostView: LView): LView {
|
||||
// Could be an LView or an LContainer. If LContainer, unwrap to find LView.
|
||||
const slotValue = hostView[nodeIndex];
|
||||
return slotValue.length >= HEADER_OFFSET ? slotValue : slotValue[HOST];
|
||||
const lView = isLView(slotValue) ? slotValue : slotValue[HOST];
|
||||
ngDevMode && assertLView(lView);
|
||||
return lView;
|
||||
}
|
||||
|
||||
export function isContentQueryHost(tNode: TNode): boolean {
|
||||
@ -128,7 +149,7 @@ export function isComponentDef<T>(def: DirectiveDef<T>): def is ComponentDef<T>
|
||||
return (def as ComponentDef<T>).template !== null;
|
||||
}
|
||||
|
||||
export function isLContainer(value: RElement | RComment | LContainer | StylingContext): boolean {
|
||||
export function isLContainer(value: any): value is LContainer {
|
||||
// Styling contexts are also arrays, but their first index contains an element node
|
||||
return Array.isArray(value) && value.length === LCONTAINER_LENGTH;
|
||||
}
|
||||
@ -138,20 +159,27 @@ export function isRootView(target: LView): boolean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the root view from any component by walking the parent `LView` until
|
||||
* Retrieve the root view from any component or `LView` by walking the parent `LView` until
|
||||
* reaching the root `LView`.
|
||||
*
|
||||
* @param component any component
|
||||
* @param componentOrLView any component or `LView`
|
||||
*/
|
||||
export function getRootView(target: LView | {}): LView {
|
||||
ngDevMode && assertDefined(target, 'component');
|
||||
let lView = Array.isArray(target) ? (target as LView) : readPatchedLView(target) !;
|
||||
export function getRootView(componentOrLView: LView | {}): LView {
|
||||
ngDevMode && assertDefined(componentOrLView, 'component');
|
||||
let lView = isLView(componentOrLView) ? componentOrLView : readPatchedLView(componentOrLView) !;
|
||||
while (lView && !(lView[FLAGS] & LViewFlags.IsRoot)) {
|
||||
lView = lView[PARENT] !;
|
||||
lView = getLViewParent(lView) !;
|
||||
}
|
||||
ngDevMode && assertLView(lView);
|
||||
return lView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the `RootContext` instance that is associated with
|
||||
* the application where the target is situated. It does this by walking the parent views until it
|
||||
* gets to the root view, then getting the context off of that.
|
||||
*
|
||||
* @param viewOrComponent the `LView` or component to get the root context for.
|
||||
*/
|
||||
export function getRootContext(viewOrComponent: LView | {}): RootContext {
|
||||
const rootView = getRootView(viewOrComponent);
|
||||
ngDevMode &&
|
||||
@ -279,6 +307,7 @@ export function findComponentView(lView: LView): LView {
|
||||
rootTNode = lView[T_HOST];
|
||||
}
|
||||
|
||||
ngDevMode && assertLView(lView);
|
||||
return lView;
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ import {addToViewTree, createEmbeddedViewAndNode, createLContainer, renderEmbedd
|
||||
import {ACTIVE_INDEX, LContainer, NATIVE, VIEWS} from './interfaces/container';
|
||||
import {TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeType, TViewNode} from './interfaces/node';
|
||||
import {RComment, RElement, isProceduralRenderer} from './interfaces/renderer';
|
||||
import {CONTAINER_INDEX, CONTEXT, LView, QUERIES, RENDERER, TView, T_HOST} from './interfaces/view';
|
||||
import {CONTEXT, LView, QUERIES, RENDERER, TView, T_HOST} from './interfaces/view';
|
||||
import {assertNodeOfPossibleTypes} from './node_assert';
|
||||
import {addRemoveViewFromContainer, appendChild, detachView, getBeforeNodeForView, insertView, nativeInsertBefore, nativeNextSibling, nativeParentNode, removeView} from './node_manipulation';
|
||||
import {getLView, getPreviousOrParentTNode} from './state';
|
||||
@ -101,15 +101,13 @@ export function createTemplateRef<T>(
|
||||
super();
|
||||
}
|
||||
|
||||
createEmbeddedView(
|
||||
context: T, container?: LContainer,
|
||||
hostTNode?: TElementNode|TContainerNode|TElementContainerNode, hostView?: LView,
|
||||
index?: number): viewEngine_EmbeddedViewRef<T> {
|
||||
createEmbeddedView(context: T, container?: LContainer, index?: number):
|
||||
viewEngine_EmbeddedViewRef<T> {
|
||||
const lView = createEmbeddedViewAndNode(
|
||||
this._tView, context, this._declarationParentView, this._hostLContainer[QUERIES],
|
||||
this._injectorIndex);
|
||||
if (container) {
|
||||
insertView(lView, container, hostView !, index !, hostTNode !.index);
|
||||
insertView(lView, container, index !);
|
||||
}
|
||||
renderEmbeddedTemplate(lView, this._tView, context);
|
||||
const viewRef = new ViewRef(lView, context, -1);
|
||||
@ -207,9 +205,7 @@ export function createContainerRef(
|
||||
viewEngine_EmbeddedViewRef<C> {
|
||||
const adjustedIdx = this._adjustIndex(index);
|
||||
const viewRef = (templateRef as any)
|
||||
.createEmbeddedView(
|
||||
context || <any>{}, this._lContainer, this._hostTNode,
|
||||
this._hostView, adjustedIdx);
|
||||
.createEmbeddedView(context || <any>{}, this._lContainer, adjustedIdx);
|
||||
(viewRef as ViewRef<any>).attachToViewContainerRef(this);
|
||||
this._viewRefs.splice(adjustedIdx, 0, viewRef);
|
||||
return viewRef;
|
||||
@ -237,7 +233,7 @@ export function createContainerRef(
|
||||
const lView = (viewRef as ViewRef<any>)._lView !;
|
||||
const adjustedIdx = this._adjustIndex(index);
|
||||
|
||||
insertView(lView, this._lContainer, this._hostView, adjustedIdx, this._hostTNode.index);
|
||||
insertView(lView, this._lContainer, adjustedIdx);
|
||||
|
||||
const beforeNode =
|
||||
getBeforeNodeForView(adjustedIdx, this._lContainer[VIEWS], this._lContainer[NATIVE]);
|
||||
@ -271,7 +267,7 @@ export function createContainerRef(
|
||||
const adjustedIdx = this._adjustIndex(index, -1);
|
||||
const view = detachView(this._lContainer, adjustedIdx);
|
||||
const wasDetached = this._viewRefs.splice(adjustedIdx, 1)[0] != null;
|
||||
return wasDetached ? new ViewRef(view, view[CONTEXT], view[CONTAINER_INDEX]) : null;
|
||||
return wasDetached ? new ViewRef(view, view[CONTEXT], -1) : null;
|
||||
}
|
||||
|
||||
private _adjustIndex(index?: number, shift: number = 0) {
|
||||
|
@ -15,7 +15,7 @@ import {checkNoChangesInRootView, checkNoChangesInternal, detectChangesInRootVie
|
||||
import {TNode, TNodeType, TViewNode} from './interfaces/node';
|
||||
import {FLAGS, HOST, LView, LViewFlags, PARENT, T_HOST} from './interfaces/view';
|
||||
import {destroyLView} from './node_manipulation';
|
||||
import {getNativeByTNode} from './util';
|
||||
import {getLViewParent, getNativeByTNode} from './util';
|
||||
|
||||
|
||||
|
||||
@ -271,7 +271,7 @@ export class ViewRef<T> implements viewEngine_EmbeddedViewRef<T>, viewEngine_Int
|
||||
}
|
||||
|
||||
private _lookUpContext(): T {
|
||||
return this._context = this._lView[PARENT] ![this._componentIndex] as T;
|
||||
return this._context = getLViewParent(this._lView) ![this._componentIndex] as T;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,10 @@ export function throwError(msg: string): never {
|
||||
}
|
||||
|
||||
export function assertDomNode(node: any) {
|
||||
assertEqual(node instanceof Node, true, 'The provided value must be an instance of a DOM Node');
|
||||
assertEqual(
|
||||
node instanceof Node ||
|
||||
(typeof node === 'object' && node.constructor.name === 'WebWorkerRenderNode'),
|
||||
true, 'The provided value must be an instance of a DOM Node');
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,10 +12,13 @@
|
||||
"name": "BLOOM_MASK"
|
||||
},
|
||||
{
|
||||
"name": "CLEAN_PROMISE"
|
||||
"name": "CHILD_HEAD"
|
||||
},
|
||||
{
|
||||
"name": "CONTAINER_INDEX"
|
||||
"name": "CHILD_TAIL"
|
||||
},
|
||||
{
|
||||
"name": "CLEAN_PROMISE"
|
||||
},
|
||||
{
|
||||
"name": "CONTEXT"
|
||||
@ -119,9 +122,6 @@
|
||||
{
|
||||
"name": "SANITIZER"
|
||||
},
|
||||
{
|
||||
"name": "TAIL"
|
||||
},
|
||||
{
|
||||
"name": "TVIEW"
|
||||
},
|
||||
@ -351,7 +351,7 @@
|
||||
"name": "getLView"
|
||||
},
|
||||
{
|
||||
"name": "getLViewChild"
|
||||
"name": "getLViewParent"
|
||||
},
|
||||
{
|
||||
"name": "getNativeAnchorNode"
|
||||
@ -470,6 +470,12 @@
|
||||
{
|
||||
"name": "isFactory"
|
||||
},
|
||||
{
|
||||
"name": "isLContainer"
|
||||
},
|
||||
{
|
||||
"name": "isLView"
|
||||
},
|
||||
{
|
||||
"name": "isNodeMatchingSelector"
|
||||
},
|
||||
|
@ -9,10 +9,13 @@
|
||||
"name": "BLOOM_MASK"
|
||||
},
|
||||
{
|
||||
"name": "CLEAN_PROMISE"
|
||||
"name": "CHILD_HEAD"
|
||||
},
|
||||
{
|
||||
"name": "CONTAINER_INDEX"
|
||||
"name": "CHILD_TAIL"
|
||||
},
|
||||
{
|
||||
"name": "CLEAN_PROMISE"
|
||||
},
|
||||
{
|
||||
"name": "CONTEXT"
|
||||
@ -50,6 +53,9 @@
|
||||
{
|
||||
"name": "INJECTOR_BLOOM_PARENT_SIZE"
|
||||
},
|
||||
{
|
||||
"name": "LCONTAINER_LENGTH"
|
||||
},
|
||||
{
|
||||
"name": "MONKEY_PATCH_KEY_NAME"
|
||||
},
|
||||
@ -98,9 +104,6 @@
|
||||
{
|
||||
"name": "SANITIZER"
|
||||
},
|
||||
{
|
||||
"name": "TAIL"
|
||||
},
|
||||
{
|
||||
"name": "TVIEW"
|
||||
},
|
||||
@ -258,7 +261,7 @@
|
||||
"name": "getLView"
|
||||
},
|
||||
{
|
||||
"name": "getLViewChild"
|
||||
"name": "getLViewParent"
|
||||
},
|
||||
{
|
||||
"name": "getNativeAnchorNode"
|
||||
@ -335,6 +338,12 @@
|
||||
{
|
||||
"name": "isFactory"
|
||||
},
|
||||
{
|
||||
"name": "isLContainer"
|
||||
},
|
||||
{
|
||||
"name": "isLView"
|
||||
},
|
||||
{
|
||||
"name": "isProceduralRenderer"
|
||||
},
|
||||
|
@ -17,15 +17,18 @@
|
||||
{
|
||||
"name": "BoundPlayerFactory"
|
||||
},
|
||||
{
|
||||
"name": "CHILD_HEAD"
|
||||
},
|
||||
{
|
||||
"name": "CHILD_TAIL"
|
||||
},
|
||||
{
|
||||
"name": "CLEANUP"
|
||||
},
|
||||
{
|
||||
"name": "CLEAN_PROMISE"
|
||||
},
|
||||
{
|
||||
"name": "CONTAINER_INDEX"
|
||||
},
|
||||
{
|
||||
"name": "CONTEXT"
|
||||
},
|
||||
@ -209,9 +212,6 @@
|
||||
{
|
||||
"name": "SkipSelf"
|
||||
},
|
||||
{
|
||||
"name": "TAIL"
|
||||
},
|
||||
{
|
||||
"name": "TNODE"
|
||||
},
|
||||
@ -720,7 +720,7 @@
|
||||
"name": "getLView"
|
||||
},
|
||||
{
|
||||
"name": "getLViewChild"
|
||||
"name": "getLViewParent"
|
||||
},
|
||||
{
|
||||
"name": "getMatchingBindingIndex"
|
||||
@ -965,6 +965,9 @@
|
||||
{
|
||||
"name": "isLContainer"
|
||||
},
|
||||
{
|
||||
"name": "isLView"
|
||||
},
|
||||
{
|
||||
"name": "isListLikeIterable"
|
||||
},
|
||||
|
@ -319,7 +319,7 @@ describe('Query API', () => {
|
||||
const template = `<needs-content-children-shallow>
|
||||
<ng-template [ngIf]="true">
|
||||
<div #q></div>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
</needs-content-children-shallow>`;
|
||||
const view = createTestCmpAndDetectChanges(MyComp0, template);
|
||||
|
||||
@ -333,7 +333,7 @@ describe('Query API', () => {
|
||||
const template = `<needs-content-children-shallow>
|
||||
<ng-template [ngIf]="true">
|
||||
<div #q directive-needs-content-child></div>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
</needs-content-children-shallow>`;
|
||||
const view = createTestCmpAndDetectChanges(MyComp0, template);
|
||||
|
||||
@ -358,7 +358,7 @@ describe('Query API', () => {
|
||||
const template = `<needs-content-children-shallow>
|
||||
<ng-container>
|
||||
<div #q></div>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</needs-content-children-shallow>`;
|
||||
const view = createTestCmpAndDetectChanges(MyComp0, template);
|
||||
|
||||
|
@ -8,14 +8,19 @@
|
||||
*/
|
||||
|
||||
import {SECURITY_SCHEMA} from '@angular/compiler/src/schema/dom_security_schema';
|
||||
import {HEADER_OFFSET, LView} from '@angular/core/src/render3/interfaces/view';
|
||||
import {setTNodeAndViewData} from '@angular/core/src/render3/state';
|
||||
|
||||
import {bypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript, bypassSanitizationTrustStyle, bypassSanitizationTrustUrl} from '../../src/sanitization/bypass';
|
||||
import {getUrlSanitizer, sanitizeHtml, sanitizeResourceUrl, sanitizeScript, sanitizeStyle, sanitizeUrl, sanitizeUrlOrResourceUrl} from '../../src/sanitization/sanitization';
|
||||
import {SecurityContext} from '../../src/sanitization/security';
|
||||
|
||||
function fakeLView(): LView {
|
||||
return Array.from({length: HEADER_OFFSET}) as LView;
|
||||
}
|
||||
|
||||
describe('sanitization', () => {
|
||||
beforeEach(() => setTNodeAndViewData(null !, [] as any));
|
||||
beforeEach(() => setTNodeAndViewData(null !, fakeLView()));
|
||||
afterEach(() => setTNodeAndViewData(null !, null !));
|
||||
class Wrap {
|
||||
constructor(private value: string) {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user