refactor(ivy): revert LNode.data into LViewData[HOST] (#26424)
PR Close #26424
This commit is contained in:
parent
45732e5b91
commit
931e603f80
|
@ -158,7 +158,6 @@ export {
|
|||
} from './sanitization/bypass';
|
||||
|
||||
export {
|
||||
LContext as ɵLContext,
|
||||
getContext as ɵgetContext
|
||||
} from './render3/context_discovery';
|
||||
|
||||
|
@ -168,6 +167,10 @@ export {
|
|||
PlayerHandler as ɵPlayerHandler,
|
||||
} from './render3/interfaces/player';
|
||||
|
||||
export {
|
||||
LContext as ɵLContext,
|
||||
} from './render3/interfaces/context';
|
||||
|
||||
export {
|
||||
addPlayer as ɵaddPlayer,
|
||||
getPlayers as ɵgetPlayers,
|
||||
|
|
|
@ -13,19 +13,22 @@ import {Injector} from '../di/injector';
|
|||
import {Sanitizer} from '../sanitization/security';
|
||||
|
||||
import {assertComponentType, assertDefined} from './assert';
|
||||
import {getLElementFromComponent, readPatchedLViewData} from './context_discovery';
|
||||
import {getComponentViewByInstance} from './context_discovery';
|
||||
import {getComponentDef} from './definition';
|
||||
import {queueInitHooks, queueLifecycleHooks} from './hooks';
|
||||
import {CLEAN_PROMISE, baseDirectiveCreate, createLViewData, createTView, detectChangesInternal, enterView, executeInitAndContentHooks, hostElement, leaveView, locateHostElement, prefillHostVars, setHostBindings} from './instructions';
|
||||
import {CLEAN_PROMISE, baseDirectiveCreate, createLViewData, createNodeAtIndex, createTView, detectChangesInternal, enterView, executeInitAndContentHooks, getOrCreateTView, leaveView, locateHostElement, prefillHostVars, resetComponentState, setHostBindings} from './instructions';
|
||||
import {ComponentDef, ComponentType} from './interfaces/definition';
|
||||
import {LElementNode, TNodeFlags} from './interfaces/node';
|
||||
import {TNodeFlags, TNodeType} from './interfaces/node';
|
||||
import {PlayerHandler} from './interfaces/player';
|
||||
import {RElement, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
|
||||
import {CONTEXT, INJECTOR, LViewData, LViewFlags, RootContext, RootContextFlags, TVIEW} from './interfaces/view';
|
||||
import {getRootView, stringify} from './util';
|
||||
import {RElement, RNode, Renderer3, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
|
||||
import {CONTEXT, HEADER_OFFSET, HOST, INJECTOR, LViewData, LViewFlags, RootContext, RootContextFlags, TVIEW} from './interfaces/view';
|
||||
import {getRootView, readElementValue, readPatchedLViewData, stringify} from './util';
|
||||
|
||||
|
||||
|
||||
// Root component will always have an element index of 0 and an injector size of 1
|
||||
const ROOT_EXPANDO_INSTRUCTIONS = [0, 1];
|
||||
|
||||
/** Options that control how the component should be bootstrapped. */
|
||||
export interface CreateComponentOptions {
|
||||
/** Which renderer factory to use. */
|
||||
|
@ -111,30 +114,29 @@ export function renderComponent<T>(
|
|||
|
||||
// The first index of the first selector is the tag name.
|
||||
const componentTag = componentDef.selectors ![0] ![0] as string;
|
||||
const hostNode = locateHostElement(rendererFactory, opts.host || componentTag);
|
||||
const hostRNode = locateHostElement(rendererFactory, opts.host || componentTag);
|
||||
const rootFlags = componentDef.onPush ? LViewFlags.Dirty | LViewFlags.IsRoot :
|
||||
LViewFlags.CheckAlways | LViewFlags.IsRoot;
|
||||
const rootContext = createRootContext(
|
||||
opts.scheduler || requestAnimationFrame.bind(window), opts.playerHandler || null);
|
||||
|
||||
const renderer = rendererFactory.createRenderer(hostRNode, componentDef);
|
||||
const rootView: LViewData = createLViewData(
|
||||
rendererFactory.createRenderer(hostNode, componentDef),
|
||||
createTView(-1, null, 1, 0, null, null, null), rootContext, rootFlags);
|
||||
renderer, createTView(-1, null, 1, 0, null, null, null), rootContext, rootFlags);
|
||||
rootView[INJECTOR] = opts.injector || null;
|
||||
|
||||
const oldView = enterView(rootView, null);
|
||||
let elementNode: LElementNode;
|
||||
let component: T;
|
||||
try {
|
||||
if (rendererFactory.begin) rendererFactory.begin();
|
||||
|
||||
// Create element node at index 0 in data array
|
||||
elementNode = hostElement(componentTag, hostNode, componentDef, sanitizer);
|
||||
const componentView =
|
||||
createRootComponentView(hostRNode, componentDef, rootView, renderer, sanitizer);
|
||||
component = createRootComponent(
|
||||
elementNode, componentDef, rootView, rootContext, opts.hostFeatures || null);
|
||||
hostRNode, componentView, componentDef, rootView, rootContext, opts.hostFeatures || null);
|
||||
|
||||
executeInitAndContentHooks();
|
||||
detectChangesInternal(elementNode.data as LViewData, component);
|
||||
detectChangesInternal(componentView, component);
|
||||
} finally {
|
||||
leaveView(oldView);
|
||||
if (rendererFactory.end) rendererFactory.end();
|
||||
|
@ -143,19 +145,55 @@ export function renderComponent<T>(
|
|||
return component;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the root component view and the root component node.
|
||||
*
|
||||
* @param rNode Render host element.
|
||||
* @param def ComponentDef
|
||||
* @param rootView The parent view where the host node is stored
|
||||
* @param renderer The current renderer
|
||||
* @param sanitizer The sanitizer, if provided
|
||||
*
|
||||
* @returns Component view created
|
||||
*/
|
||||
export function createRootComponentView(
|
||||
rNode: RElement | null, def: ComponentDef<any>, rootView: LViewData, renderer: Renderer3,
|
||||
sanitizer?: Sanitizer | null): LViewData {
|
||||
resetComponentState();
|
||||
const tView = rootView[TVIEW];
|
||||
const componentView = createLViewData(
|
||||
renderer,
|
||||
getOrCreateTView(
|
||||
def.template, def.consts, def.vars, def.directiveDefs, def.pipeDefs, def.viewQuery),
|
||||
null, def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways, sanitizer);
|
||||
const tNode = createNodeAtIndex(0, TNodeType.Element, rNode, null, null, componentView);
|
||||
|
||||
if (tView.firstTemplatePass) {
|
||||
tView.expandoInstructions = ROOT_EXPANDO_INSTRUCTIONS.slice();
|
||||
if (def.diPublic) def.diPublic(def);
|
||||
tNode.flags =
|
||||
rootView.length << TNodeFlags.DirectiveStartingIndexShift | TNodeFlags.isComponent;
|
||||
}
|
||||
|
||||
// Store component view at node index, with node as the HOST
|
||||
componentView[HOST] = rootView[HEADER_OFFSET];
|
||||
return rootView[HEADER_OFFSET] = componentView;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a root component and sets it up with features and host bindings. Shared by
|
||||
* renderComponent() and ViewContainerRef.createComponent().
|
||||
*/
|
||||
export function createRootComponent<T>(
|
||||
elementNode: LElementNode, componentDef: ComponentDef<T>, rootView: LViewData,
|
||||
rootContext: RootContext, hostFeatures: HostFeature[] | null): any {
|
||||
hostRNode: RNode | null, componentView: LViewData, componentDef: ComponentDef<T>,
|
||||
rootView: LViewData, rootContext: RootContext, hostFeatures: HostFeature[] | null): any {
|
||||
// Create directive instance with factory() and store at next index in viewData
|
||||
const component =
|
||||
baseDirectiveCreate(rootView.length, componentDef.factory() as T, componentDef, elementNode);
|
||||
baseDirectiveCreate(rootView.length, componentDef.factory() as T, componentDef, hostRNode);
|
||||
|
||||
rootContext.components.push(component);
|
||||
(elementNode.data as LViewData)[CONTEXT] = component;
|
||||
componentView[CONTEXT] = component;
|
||||
|
||||
hostFeatures && hostFeatures.forEach((feature) => feature(component, componentDef));
|
||||
if (rootView[TVIEW].firstTemplatePass) prefillHostVars(componentDef.hostVars);
|
||||
|
@ -217,7 +255,7 @@ function getRootContext(component: any): RootContext {
|
|||
* @param component Component for which the host element should be retrieved.
|
||||
*/
|
||||
export function getHostElement<T>(component: T): HTMLElement {
|
||||
return getLElementFromComponent(component).native as any;
|
||||
return readElementValue(getComponentViewByInstance(component)).native as HTMLElement;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,13 +17,14 @@ import {RendererFactory2} from '../render/api';
|
|||
import {Type} from '../type';
|
||||
|
||||
import {assertComponentType, assertDefined} from './assert';
|
||||
import {LifecycleHooksFeature, createRootComponent, createRootContext} from './component';
|
||||
import {LifecycleHooksFeature, createRootComponent, createRootComponentView, createRootContext} from './component';
|
||||
import {getComponentDef} from './definition';
|
||||
import {adjustBlueprintForNewNode, createLViewData, createNodeAtIndex, createTView, elementCreate, enterView, getTNode, hostElement, locateHostElement, renderEmbeddedTemplate} from './instructions';
|
||||
import {adjustBlueprintForNewNode, createLViewData, createNodeAtIndex, createTView, elementCreate, enterView, locateHostElement, renderEmbeddedTemplate} from './instructions';
|
||||
import {ComponentDef, RenderFlags} from './interfaces/definition';
|
||||
import {LElementNode, TElementNode, TNode, TNodeType, TViewNode} from './interfaces/node';
|
||||
import {TElementNode, TNode, TNodeType, TViewNode} from './interfaces/node';
|
||||
import {RElement, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
|
||||
import {FLAGS, INJECTOR, LViewData, LViewFlags, RootContext, TVIEW} from './interfaces/view';
|
||||
import {getTNode} from './util';
|
||||
import {createElementRef} from './view_engine_compatibility';
|
||||
import {RootViewRef, ViewRef} from './view_ref';
|
||||
|
||||
|
@ -109,7 +110,7 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
|
|||
rendererFactory = domRendererFactory3;
|
||||
}
|
||||
|
||||
const hostNode = isInternalRootView ?
|
||||
const hostRNode = isInternalRootView ?
|
||||
elementCreate(this.selector, rendererFactory.createRenderer(null, this.componentDef)) :
|
||||
locateHostElement(rendererFactory, rootSelectorOrNode);
|
||||
|
||||
|
@ -122,24 +123,23 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
|
|||
ngModule.injector.get(ROOT_CONTEXT) :
|
||||
createRootContext(requestAnimationFrame.bind(window));
|
||||
|
||||
const renderer = rendererFactory.createRenderer(hostRNode, this.componentDef);
|
||||
// Create the root view. Uses empty TView and ContentTemplate.
|
||||
const rootView: LViewData = createLViewData(
|
||||
rendererFactory.createRenderer(hostNode, this.componentDef),
|
||||
createTView(-1, null, 1, 0, null, null, null), rootContext, rootFlags);
|
||||
renderer, createTView(-1, null, 1, 0, null, null, null), rootContext, rootFlags);
|
||||
rootView[INJECTOR] = ngModule && ngModule.injector || null;
|
||||
|
||||
// rootView is the parent when bootstrapping
|
||||
const oldView = enterView(rootView, null);
|
||||
|
||||
let component: T;
|
||||
let elementNode: LElementNode;
|
||||
let tElementNode: TElementNode;
|
||||
try {
|
||||
if (rendererFactory.begin) rendererFactory.begin();
|
||||
|
||||
// Create element node at index 0 in data array
|
||||
elementNode = hostElement(componentTag, hostNode, this.componentDef);
|
||||
tElementNode = getTNode(0) as TElementNode;
|
||||
const componentView =
|
||||
createRootComponentView(hostRNode, this.componentDef, rootView, renderer);
|
||||
tElementNode = getTNode(0, rootView) as TElementNode;
|
||||
|
||||
// Transform the arrays of native nodes into a LNode structure that can be consumed by the
|
||||
// projection instruction. This is needed to support the reprojection of these nodes.
|
||||
|
@ -165,10 +165,10 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
|
|||
// executed here?
|
||||
// Angular 5 reference: https://stackblitz.com/edit/lifecycle-hooks-vcref
|
||||
component = createRootComponent(
|
||||
elementNode, this.componentDef, rootView, rootContext, [LifecycleHooksFeature]);
|
||||
hostRNode, componentView, this.componentDef, rootView, rootContext,
|
||||
[LifecycleHooksFeature]);
|
||||
|
||||
// Execute the template in creation mode only, and then turn off the CreationMode flag
|
||||
const componentView = elementNode.data as LViewData;
|
||||
renderEmbeddedTemplate(componentView, componentView[TVIEW], component, RenderFlags.Create);
|
||||
componentView[FLAGS] &= ~LViewFlags.CreationMode;
|
||||
} finally {
|
||||
|
|
|
@ -8,59 +8,12 @@
|
|||
import './ng_dev_mode';
|
||||
|
||||
import {assertEqual} from './assert';
|
||||
import {ACTIVE_INDEX, HOST_NATIVE, LContainer} from './interfaces/container';
|
||||
import {LContext, MONKEY_PATCH_KEY_NAME} from './interfaces/context';
|
||||
import {LElementNode, TNode, TNodeFlags} from './interfaces/node';
|
||||
import {RElement} from './interfaces/renderer';
|
||||
import {StylingContext, StylingIndex} from './interfaces/styling';
|
||||
import {CONTEXT, HEADER_OFFSET, LViewData, TVIEW} from './interfaces/view';
|
||||
import {CONTEXT, HEADER_OFFSET, HOST, LViewData, TVIEW} from './interfaces/view';
|
||||
import {getComponentViewByIndex, readElementValue, readPatchedData} from './util';
|
||||
|
||||
/**
|
||||
* This property will be monkey-patched on elements, components and directives
|
||||
*/
|
||||
export const MONKEY_PATCH_KEY_NAME = '__ngContext__';
|
||||
|
||||
/**
|
||||
* The internal view context which is specific to a given DOM element, directive or
|
||||
* component instance. Each value in here (besides the LViewData and element node details)
|
||||
* can be present, null or undefined. If undefined then it implies the value has not been
|
||||
* looked up yet, otherwise, if null, then a lookup was executed and nothing was found.
|
||||
*
|
||||
* Each value will get filled when the respective value is examined within the getContext
|
||||
* function. The component, element and each directive instance will share the same instance
|
||||
* of the context.
|
||||
*/
|
||||
export interface LContext {
|
||||
/**
|
||||
* The component's parent view data.
|
||||
*/
|
||||
lViewData: LViewData;
|
||||
|
||||
/**
|
||||
* The index instance of the node.
|
||||
*/
|
||||
nodeIndex: number;
|
||||
|
||||
/**
|
||||
* The instance of the DOM node that is attached to the lNode.
|
||||
*/
|
||||
native: RElement;
|
||||
|
||||
/**
|
||||
* The instance of the Component node.
|
||||
*/
|
||||
component: {}|null|undefined;
|
||||
|
||||
/**
|
||||
* The list of active directives that exist on this element.
|
||||
*/
|
||||
directives: any[]|null|undefined;
|
||||
|
||||
/**
|
||||
* The map of local references (local reference name => element or directive instance) that exist
|
||||
* on this element.
|
||||
*/
|
||||
localRefs: {[key: string]: any}|null|undefined;
|
||||
}
|
||||
|
||||
/** Returns the matching `LContext` data for a given DOM node, directive or component instance.
|
||||
*
|
||||
|
@ -187,29 +140,27 @@ function createLContext(lViewData: LViewData, lNodeIndex: number, native: REleme
|
|||
}
|
||||
|
||||
/**
|
||||
* A simplified lookup function for finding the LElementNode from a component instance.
|
||||
* Takes a component instance and returns the view for that component.
|
||||
*
|
||||
* This function exists for tree-shaking purposes to avoid having to pull in everything
|
||||
* that `getContext` has in the event that an Angular application doesn't need to have
|
||||
* any programmatic access to an element's context (only change detection uses this function).
|
||||
* @param componentInstance
|
||||
* @returns The component's view
|
||||
*/
|
||||
export function getLElementFromComponent(componentInstance: {}): LElementNode {
|
||||
export function getComponentViewByInstance(componentInstance: {}): LViewData {
|
||||
let lViewData = readPatchedData(componentInstance);
|
||||
let lNode: LElementNode;
|
||||
let view: LViewData;
|
||||
|
||||
if (Array.isArray(lViewData)) {
|
||||
const lNodeIndex = findViaComponent(lViewData, componentInstance);
|
||||
lNode = readElementValue(lViewData[lNodeIndex]);
|
||||
const context = createLContext(lViewData, lNodeIndex, lNode.native);
|
||||
view = getComponentViewByIndex(lNodeIndex, lViewData);
|
||||
const context = createLContext(lViewData, lNodeIndex, (view[HOST] as LElementNode).native);
|
||||
context.component = componentInstance;
|
||||
attachPatchData(componentInstance, context);
|
||||
attachPatchData(context.native, context);
|
||||
} else {
|
||||
const context = lViewData as any as LContext;
|
||||
lNode = readElementValue(context.lViewData[context.nodeIndex]);
|
||||
view = getComponentViewByIndex(context.nodeIndex, context.lViewData);
|
||||
}
|
||||
|
||||
return lNode;
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -220,22 +171,6 @@ export function attachPatchData(target: any, data: LViewData | LContext) {
|
|||
target[MONKEY_PATCH_KEY_NAME] = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the monkey-patch value data present on the target (which could be
|
||||
* a component, directive or a DOM node).
|
||||
*/
|
||||
export function readPatchedData(target: any): LViewData|LContext|null {
|
||||
return target[MONKEY_PATCH_KEY_NAME];
|
||||
}
|
||||
|
||||
export function readPatchedLViewData(target: any): LViewData|null {
|
||||
const value = readPatchedData(target);
|
||||
if (value) {
|
||||
return Array.isArray(value) ? value : (value as LContext).lViewData;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function isComponentInstance(instance: any): boolean {
|
||||
return instance && instance.constructor && instance.constructor.ngComponentDef;
|
||||
}
|
||||
|
@ -282,14 +217,14 @@ function findViaComponent(lViewData: LViewData, componentInstance: {}): number {
|
|||
if (componentIndices) {
|
||||
for (let i = 0; i < componentIndices.length; i++) {
|
||||
const elementComponentIndex = componentIndices[i];
|
||||
const lNodeData = readElementValue(lViewData[elementComponentIndex] !).data !;
|
||||
if (lNodeData[CONTEXT] === componentInstance) {
|
||||
const componentView = getComponentViewByIndex(elementComponentIndex, lViewData);
|
||||
if (componentView[CONTEXT] === componentInstance) {
|
||||
return elementComponentIndex;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const rootNode = lViewData[HEADER_OFFSET];
|
||||
const rootComponent = rootNode.data[CONTEXT];
|
||||
const rootComponentView = getComponentViewByIndex(HEADER_OFFSET, lViewData);
|
||||
const rootComponent = rootComponentView[CONTEXT];
|
||||
if (rootComponent === componentInstance) {
|
||||
// we are dealing with the root element here therefore we know that the
|
||||
// element is the very first element after the HEADER data in the lView
|
||||
|
@ -391,27 +326,3 @@ function getDirectiveEndIndex(tNode: TNode, startIndex: number): number {
|
|||
const count = tNode.flags & TNodeFlags.DirectiveCountMask;
|
||||
return count ? (startIndex + count) : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the value of a slot in `LViewData` and returns the element node.
|
||||
*
|
||||
* Normally, element nodes are stored flat, but if the node has styles/classes on it,
|
||||
* it might be wrapped in a styling context. Or if that node has a directive that injects
|
||||
* ViewContainerRef, it may be wrapped in an LContainer.
|
||||
*
|
||||
* @param value The initial value in `LViewData`
|
||||
*/
|
||||
export function readElementValue(value: LElementNode | StylingContext | LContainer): LElementNode {
|
||||
if (Array.isArray(value)) {
|
||||
if (typeof value[ACTIVE_INDEX] === 'number') {
|
||||
// This is an LContainer. It may also have a styling context.
|
||||
value = value[HOST_NATIVE] as LElementNode | StylingContext;
|
||||
return Array.isArray(value) ? value[StylingIndex.ElementPosition] ! : value;
|
||||
} else {
|
||||
// This is a StylingContext, which stores the element node at 0.
|
||||
return value[StylingIndex.ElementPosition] as LElementNode;
|
||||
}
|
||||
} else {
|
||||
return value; // Regular LNode is stored here
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,10 +8,13 @@
|
|||
import {Injector} from '../di/injector';
|
||||
|
||||
import {assertDefined} from './assert';
|
||||
import {LContext, discoverDirectives, discoverLocalRefs, getContext, isComponentInstance, readPatchedLViewData} from './context_discovery';
|
||||
import {discoverDirectives, discoverLocalRefs, getContext, isComponentInstance} from './context_discovery';
|
||||
import {NodeInjector} from './di';
|
||||
import {LElementNode, TElementNode, TNode, TNodeFlags} from './interfaces/node';
|
||||
import {LContext} from './interfaces/context';
|
||||
import {TElementNode, TNode, TNodeFlags} from './interfaces/node';
|
||||
import {CONTEXT, FLAGS, LViewData, LViewFlags, PARENT, RootContext, TVIEW} from './interfaces/view';
|
||||
import {getComponentViewByIndex, readPatchedLViewData} from './util';
|
||||
|
||||
|
||||
/**
|
||||
* NOTE: The following functions might not be ideal for core usage in Angular...
|
||||
|
@ -61,8 +64,8 @@ export function getHostComponent<T = {}>(target: {}): T|null {
|
|||
const context = loadContext(target);
|
||||
const tNode = context.lViewData[TVIEW].data[context.nodeIndex] as TNode;
|
||||
if (tNode.flags & TNodeFlags.isComponent) {
|
||||
const lNode = context.lViewData[context.nodeIndex] as LElementNode;
|
||||
return lNode.data ![CONTEXT] as any as T;
|
||||
const componentView = getComponentViewByIndex(context.nodeIndex, context.lViewData);
|
||||
return componentView[CONTEXT] as any as T;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
*/
|
||||
|
||||
import {assertEqual, assertLessThan} from './assert';
|
||||
import {NO_CHANGE, _getViewData, adjustBlueprintForNewNode, bindingUpdated, bindingUpdated2, bindingUpdated3, bindingUpdated4, createNodeAtIndex, getRenderer, getTNode, load, loadElement, resetComponentState} from './instructions';
|
||||
import {NO_CHANGE, _getViewData, adjustBlueprintForNewNode, bindingUpdated, bindingUpdated2, bindingUpdated3, bindingUpdated4, createNodeAtIndex, getRenderer, load, loadElement, resetComponentState} from './instructions';
|
||||
import {LContainer, NATIVE, RENDER_PARENT} from './interfaces/container';
|
||||
import {LContainerNode, LNode, TElementNode, TNode, TNodeType} from './interfaces/node';
|
||||
import {StylingContext} from './interfaces/styling';
|
||||
import {BINDING_INDEX, HEADER_OFFSET, HOST_NODE, TVIEW} from './interfaces/view';
|
||||
import {appendChild, createTextNode, removeChild} from './node_manipulation';
|
||||
import {getLNode, isLContainer, stringify} from './util';
|
||||
import {getNative, getTNode, isLContainer, stringify} from './util';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
@ -272,8 +273,7 @@ function appendI18nNode(tNode: TNode, parentTNode: TNode, previousTNode: TNode):
|
|||
}
|
||||
}
|
||||
|
||||
const native = getLNode(tNode, viewData).native;
|
||||
appendChild(native, tNode, viewData);
|
||||
appendChild(getNative(tNode, viewData), tNode, viewData);
|
||||
|
||||
const slotValue = viewData[tNode.index];
|
||||
if (tNode.type !== TNodeType.Container && isLContainer(slotValue)) {
|
||||
|
@ -320,7 +320,7 @@ export function i18nApply(startIndex: number, instructions: I18nInstruction[]):
|
|||
}
|
||||
|
||||
const renderer = getRenderer();
|
||||
const startTNode = getTNode(startIndex);
|
||||
const startTNode = getTNode(startIndex, viewData);
|
||||
let localParentTNode: TNode = startTNode.parent || viewData[HOST_NODE] !;
|
||||
let localPreviousTNode: TNode = localParentTNode;
|
||||
resetComponentState(); // We don't want to add to the tree with the wrong previous node
|
||||
|
@ -329,7 +329,7 @@ export function i18nApply(startIndex: number, instructions: I18nInstruction[]):
|
|||
const instruction = instructions[i] as number;
|
||||
switch (instruction & I18nInstructions.InstructionMask) {
|
||||
case I18nInstructions.Element:
|
||||
const elementTNode = getTNode(instruction & I18nInstructions.IndexMask);
|
||||
const elementTNode = getTNode(instruction & I18nInstructions.IndexMask, viewData);
|
||||
localPreviousTNode = appendI18nNode(elementTNode, localParentTNode, localPreviousTNode);
|
||||
localParentTNode = elementTNode;
|
||||
break;
|
||||
|
@ -338,7 +338,7 @@ export function i18nApply(startIndex: number, instructions: I18nInstruction[]):
|
|||
case I18nInstructions.Any:
|
||||
const nodeIndex = instruction & I18nInstructions.IndexMask;
|
||||
localPreviousTNode =
|
||||
appendI18nNode(getTNode(nodeIndex), localParentTNode, localPreviousTNode);
|
||||
appendI18nNode(getTNode(nodeIndex, viewData), localParentTNode, localPreviousTNode);
|
||||
break;
|
||||
case I18nInstructions.Text:
|
||||
if (ngDevMode) {
|
||||
|
@ -365,7 +365,7 @@ export function i18nApply(startIndex: number, instructions: I18nInstruction[]):
|
|||
}
|
||||
const removeIndex = instruction & I18nInstructions.IndexMask;
|
||||
const removedNode: LNode|LContainerNode = loadElement(removeIndex);
|
||||
const removedTNode = getTNode(removeIndex);
|
||||
const removedTNode = getTNode(removeIndex, viewData);
|
||||
removeChild(removedTNode, removedNode.native || null, viewData);
|
||||
|
||||
const slotValue = load(removeIndex) as LNode | LContainer | StylingContext;
|
||||
|
|
|
@ -13,23 +13,24 @@ import {Sanitizer} from '../sanitization/security';
|
|||
import {StyleSanitizeFn} from '../sanitization/style_sanitizer';
|
||||
|
||||
import {assertDefined, assertEqual, assertLessThan, assertNotEqual} from './assert';
|
||||
import {attachPatchData, getLElementFromComponent, readElementValue, readPatchedLViewData} from './context_discovery';
|
||||
import {attachPatchData, getComponentViewByInstance} from './context_discovery';
|
||||
import {throwCyclicDependencyError, throwErrorIfNoChangesMode, throwMultipleComponentError} from './errors';
|
||||
import {executeHooks, executeInitHooks, queueInitHooks, queueLifecycleHooks} from './hooks';
|
||||
import {ACTIVE_INDEX, HOST_NATIVE, LContainer, RENDER_PARENT, VIEWS} from './interfaces/container';
|
||||
import {ACTIVE_INDEX, LContainer, VIEWS} from './interfaces/container';
|
||||
import {ComponentDef, ComponentQuery, ComponentTemplate, DirectiveDef, DirectiveDefListOrFactory, InitialStylingFlags, PipeDefListOrFactory, RenderFlags} from './interfaces/definition';
|
||||
import {INJECTOR_SIZE} from './interfaces/injector';
|
||||
import {AttributeMarker, InitialInputData, InitialInputs, LContainerNode, LElementContainerNode, LElementNode, LNode, LProjectionNode, LTextNode, LViewNode, LocalRefExtractor, PropertyAliasValue, PropertyAliases, TAttributes, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, TProjectionNode, TViewNode} from './interfaces/node';
|
||||
import {AttributeMarker, InitialInputData, InitialInputs, LContainerNode, LElementContainerNode, LElementNode, LTextNode, LocalRefExtractor, PropertyAliasValue, PropertyAliases, TAttributes, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, TProjectionNode, TViewNode} from './interfaces/node';
|
||||
import {CssSelectorList, NG_PROJECT_AS_ATTR_NAME} from './interfaces/projection';
|
||||
import {LQueries} from './interfaces/query';
|
||||
import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, RendererFactory3, isProceduralRenderer} from './interfaces/renderer';
|
||||
import {StylingContext} from './interfaces/styling';
|
||||
import {BINDING_INDEX, CLEANUP, CONTAINER_INDEX, CONTENT_QUERIES, CONTEXT, CurrentMatchesList, DECLARATION_VIEW, FLAGS, HEADER_OFFSET, HOST_NODE, INJECTOR, LViewData, LViewFlags, NEXT, OpaqueViewState, PARENT, QUERIES, RENDERER, RootContext, RootContextFlags, SANITIZER, TAIL, TVIEW, TView} from './interfaces/view';
|
||||
import {BINDING_INDEX, CLEANUP, CONTAINER_INDEX, CONTENT_QUERIES, CONTEXT, CurrentMatchesList, DECLARATION_VIEW, FLAGS, HEADER_OFFSET, HOST, HOST_NODE, INJECTOR, LViewData, LViewFlags, NEXT, OpaqueViewState, PARENT, QUERIES, RENDERER, RootContext, RootContextFlags, SANITIZER, TAIL, TVIEW, TView} from './interfaces/view';
|
||||
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
|
||||
import {appendChild, appendProjectedNode, createTextNode, findComponentView, getHostElementNode, getLViewChild, getRenderParent, insertView, removeView} from './node_manipulation';
|
||||
import {appendChild, appendProjectedNode, createTextNode, findComponentView, getLViewChild, getRenderParent, insertView, removeView} from './node_manipulation';
|
||||
import {isNodeMatchingSelectorList, matchingSelectorIndex} from './node_selector_matcher';
|
||||
import {allocStylingContext, createStylingContextTemplate, renderStyling as renderElementStyles, updateClassProp as updateElementClassProp, updateStyleProp as updateElementStyleProp, updateStylingMap} from './styling/class_and_style_bindings';
|
||||
import {assertDataInRangeInternal, getLNode, getRootView, isContentQueryHost, isDifferent, isLContainer, loadElementInternal, loadInternal, stringify} from './util';
|
||||
import {createStylingContextTemplate, renderStyling as renderElementStyles, updateClassProp as updateElementClassProp, updateStyleProp as updateElementStyleProp, updateStylingMap} from './styling/class_and_style_bindings';
|
||||
import {getStylingContext} from './styling/util';
|
||||
import {assertDataInRangeInternal, getComponentViewByIndex, getNative, getRootView, getTNode, isComponent, isContentQueryHost, isDifferent, loadElementInternal, loadInternal, readPatchedLViewData, stringify} from './util';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
@ -139,12 +140,6 @@ export function restoreView(viewToRestore: OpaqueViewState) {
|
|||
/** Used to set the parent property when nodes are created and track query results. */
|
||||
let previousOrParentTNode: TNode;
|
||||
|
||||
export function getPreviousOrParentNode(): LNode|null {
|
||||
return previousOrParentTNode == null || previousOrParentTNode === viewData[HOST_NODE] ?
|
||||
getHostElementNode(viewData) :
|
||||
getLNode(previousOrParentTNode, viewData);
|
||||
}
|
||||
|
||||
export function getPreviousOrParentTNode(): TNode {
|
||||
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
|
||||
return previousOrParentTNode;
|
||||
|
@ -252,9 +247,6 @@ export function getBindingRoot() {
|
|||
return bindingRootIndex;
|
||||
}
|
||||
|
||||
// Root component will always have an element index of 0 and an injector size of 1
|
||||
const ROOT_EXPANDO_INSTRUCTIONS = [0, 1];
|
||||
|
||||
const enum BindingDirection {
|
||||
Input,
|
||||
Output,
|
||||
|
@ -413,8 +405,8 @@ export function createLViewData<T>(
|
|||
renderer: Renderer3, tView: TView, context: T | null, flags: LViewFlags,
|
||||
sanitizer?: Sanitizer | null): LViewData {
|
||||
const instance = tView.blueprint.slice() as LViewData;
|
||||
instance[PARENT] = instance[DECLARATION_VIEW] = viewData;
|
||||
instance[FLAGS] = flags | LViewFlags.CreationMode | LViewFlags.Attached | LViewFlags.RunInit;
|
||||
instance[PARENT] = instance[DECLARATION_VIEW] = viewData;
|
||||
instance[CONTEXT] = context;
|
||||
instance[INJECTOR] = viewData ? viewData[INJECTOR] : null;
|
||||
instance[RENDERER] = renderer;
|
||||
|
@ -422,17 +414,6 @@ export function createLViewData<T>(
|
|||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creation of LNode object is extracted to a separate function so we always create LNode object
|
||||
* with the same shape
|
||||
* (same properties assigned in the same order).
|
||||
*/
|
||||
export function createLNodeObject(
|
||||
type: TNodeType, native: RText | RElement | RComment | null, state: any): LElementNode&
|
||||
LTextNode&LViewNode&LContainerNode&LProjectionNode {
|
||||
return {native: native as any, data: state};
|
||||
}
|
||||
|
||||
/**
|
||||
* A common way of creating the LNode to make sure that all of them have same shape to
|
||||
* keep the execution code monomorphic and fast.
|
||||
|
@ -456,14 +437,14 @@ export function createNodeAtIndex(
|
|||
attrs: TAttributes | null, data: null): TContainerNode;
|
||||
export function createNodeAtIndex(
|
||||
index: number, type: TNodeType.Projection, native: null, name: null, attrs: TAttributes | null,
|
||||
lProjection: null): TProjectionNode;
|
||||
data: null): TProjectionNode;
|
||||
export function createNodeAtIndex(
|
||||
index: number, type: TNodeType.ElementContainer, native: RComment, name: null,
|
||||
attrs: TAttributes | null, data: null): TElementContainerNode;
|
||||
export function createNodeAtIndex(
|
||||
index: number, type: TNodeType, native: RText | RElement | RComment | null, name: string | null,
|
||||
attrs: TAttributes | null, state?: null | LViewData | LContainer): TElementNode&TViewNode&
|
||||
TContainerNode&TElementContainerNode&TProjectionNode {
|
||||
attrs: TAttributes | null, state?: null | LViewData): TElementNode&TViewNode&TContainerNode&
|
||||
TElementContainerNode&TProjectionNode {
|
||||
const parent =
|
||||
isParent ? previousOrParentTNode : previousOrParentTNode && previousOrParentTNode.parent;
|
||||
|
||||
|
@ -473,7 +454,7 @@ export function createNodeAtIndex(
|
|||
const tParent = parentInSameView ? parent as TElementNode | TContainerNode : null;
|
||||
|
||||
const isState = state != null;
|
||||
const node = createLNodeObject(type, native, isState ? state as any : null);
|
||||
const node = {native: native as any};
|
||||
let tNode: TNode;
|
||||
|
||||
if (index === -1 || type === TNodeType.View) {
|
||||
|
@ -574,10 +555,10 @@ export function resetComponentState() {
|
|||
*/
|
||||
export function renderTemplate<T>(
|
||||
hostNode: RElement, templateFn: ComponentTemplate<T>, consts: number, vars: number, context: T,
|
||||
providedRendererFactory: RendererFactory3, host: LElementNode | null,
|
||||
providedRendererFactory: RendererFactory3, hostView: LViewData | null,
|
||||
directives?: DirectiveDefListOrFactory | null, pipes?: PipeDefListOrFactory | null,
|
||||
sanitizer?: Sanitizer | null): LElementNode {
|
||||
if (host == null) {
|
||||
sanitizer?: Sanitizer | null): LViewData {
|
||||
if (hostView == null) {
|
||||
resetComponentState();
|
||||
rendererFactory = providedRendererFactory;
|
||||
renderer = providedRendererFactory.createRenderer(null, null);
|
||||
|
@ -588,16 +569,13 @@ export function renderTemplate<T>(
|
|||
|
||||
const componentTView =
|
||||
getOrCreateTView(templateFn, consts, vars, directives || null, pipes || null, null);
|
||||
const componentLView =
|
||||
hostView =
|
||||
createLViewData(renderer, componentTView, context, LViewFlags.CheckAlways, sanitizer);
|
||||
createNodeAtIndex(0, TNodeType.Element, hostNode, null, null, componentLView);
|
||||
host = loadElement(0);
|
||||
createNodeAtIndex(0, TNodeType.Element, hostNode, null, null, hostView);
|
||||
}
|
||||
const hostView = host.data !;
|
||||
ngDevMode && assertDefined(hostView, 'Host node should have an LView defined in host.data.');
|
||||
renderComponentOrTemplate(hostView, context, templateFn);
|
||||
|
||||
return host;
|
||||
return hostView;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -877,10 +855,6 @@ export function elementCreate(name: string, overriddenRenderer?: Renderer3): REl
|
|||
return native;
|
||||
}
|
||||
|
||||
function nativeNodeLocalRefExtractor(tNode: TNode, currentView: LViewData): RNode {
|
||||
return getLNode(tNode, currentView).native;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates directive instances and populates local refs.
|
||||
*
|
||||
|
@ -889,8 +863,7 @@ function nativeNodeLocalRefExtractor(tNode: TNode, currentView: LViewData): RNod
|
|||
* @param localRefExtractor mapping function that extracts local ref value from LNode
|
||||
*/
|
||||
function createDirectivesAndLocals(
|
||||
localRefs: string[] | null | undefined,
|
||||
localRefExtractor: LocalRefExtractor = nativeNodeLocalRefExtractor) {
|
||||
localRefs: string[] | null | undefined, localRefExtractor: LocalRefExtractor = getNative) {
|
||||
if (!bindingsEnabled) return;
|
||||
if (firstTemplatePass) {
|
||||
ngDevMode && ngDevMode.firstTemplatePass++;
|
||||
|
@ -1096,7 +1069,7 @@ function saveResolvedLocalsInData(localRefExtractor: LocalRefExtractor): void {
|
|||
* @param pipes Pipe defs that should be saved on TView
|
||||
* @returns TView
|
||||
*/
|
||||
function getOrCreateTView(
|
||||
export function getOrCreateTView(
|
||||
templateFn: ComponentTemplate<any>, consts: number, vars: number,
|
||||
directives: DirectiveDefListOrFactory | null, pipes: PipeDefListOrFactory | null,
|
||||
viewQuery: ComponentQuery<any>| null): TView {
|
||||
|
@ -1235,35 +1208,6 @@ export function locateHostElement(
|
|||
return rNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the host LNode.
|
||||
*
|
||||
* @param rNode Render host element.
|
||||
* @param def ComponentDef
|
||||
*
|
||||
* @returns LElementNode created
|
||||
*/
|
||||
export function hostElement(
|
||||
tag: string, rNode: RElement | null, def: ComponentDef<any>,
|
||||
sanitizer?: Sanitizer | null): LElementNode {
|
||||
resetComponentState();
|
||||
const tNode = createNodeAtIndex(
|
||||
0, TNodeType.Element, rNode, null, null,
|
||||
createLViewData(
|
||||
renderer,
|
||||
getOrCreateTView(
|
||||
def.template, def.consts, def.vars, def.directiveDefs, def.pipeDefs, def.viewQuery),
|
||||
null, def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways, sanitizer));
|
||||
|
||||
if (firstTemplatePass) {
|
||||
tView.expandoInstructions = ROOT_EXPANDO_INSTRUCTIONS.slice();
|
||||
if (def.diPublic) def.diPublic(def);
|
||||
tNode.flags =
|
||||
viewData.length << TNodeFlags.DirectiveStartingIndexShift | TNodeFlags.isComponent;
|
||||
}
|
||||
return viewData[HEADER_OFFSET];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an event listener to the current node.
|
||||
*
|
||||
|
@ -1282,17 +1226,17 @@ export function listener(
|
|||
|
||||
// add native event listener - applicable to elements only
|
||||
if (tNode.type === TNodeType.Element) {
|
||||
const node = getPreviousOrParentNode() as LElementNode;
|
||||
const native = getNative(previousOrParentTNode, viewData) as RElement;
|
||||
ngDevMode && ngDevMode.rendererAddEventListener++;
|
||||
|
||||
// In order to match current behavior, native DOM event listeners must be added for all
|
||||
// events (including outputs).
|
||||
if (isProceduralRenderer(renderer)) {
|
||||
const cleanupFn = renderer.listen(node.native, eventName, listenerFn);
|
||||
const cleanupFn = renderer.listen(native, eventName, listenerFn);
|
||||
storeCleanupFn(viewData, cleanupFn);
|
||||
} else {
|
||||
const wrappedListener = wrapListenerWithPreventDefault(listenerFn);
|
||||
node.native.addEventListener(eventName, wrappedListener, useCapture);
|
||||
native.addEventListener(eventName, wrappedListener, useCapture);
|
||||
const cleanupInstances = getCleanup(viewData);
|
||||
cleanupInstances.push(wrappedListener);
|
||||
if (firstTemplatePass) {
|
||||
|
@ -1421,7 +1365,7 @@ export function elementProperty<T>(
|
|||
index: number, propName: string, value: T | NO_CHANGE, sanitizer?: SanitizerFn): void {
|
||||
if (value === NO_CHANGE) return;
|
||||
const node = loadElement(index) as LElementNode | LContainerNode | LElementContainerNode;
|
||||
const tNode = getTNode(index);
|
||||
const tNode = getTNode(index, viewData);
|
||||
// if tNode.inputs is undefined, a listener has created outputs, but inputs haven't
|
||||
// yet been checked
|
||||
if (tNode && tNode.inputs === undefined) {
|
||||
|
@ -1433,7 +1377,7 @@ export function elementProperty<T>(
|
|||
let dataValue: PropertyAliasValue|undefined;
|
||||
if (inputData && (dataValue = inputData[propName])) {
|
||||
setInputsForProperty(dataValue, value);
|
||||
if (tNode.type === TNodeType.Element) markDirtyIfOnPush(node as LElementNode);
|
||||
if (isComponent(tNode)) markDirtyIfOnPush(index + HEADER_OFFSET);
|
||||
} else if (tNode.type === TNodeType.Element) {
|
||||
// It is assumed that the sanitizer is only added when the compiler determines that the property
|
||||
// is risky, so sanitization can be done without further checks.
|
||||
|
@ -1583,7 +1527,7 @@ function generatePropertyAliases(
|
|||
*/
|
||||
export function elementClassProp<T>(
|
||||
index: number, stylingIndex: number, value: T | NO_CHANGE): void {
|
||||
updateElementClassProp(getStylingContext(index), stylingIndex, value ? true : false);
|
||||
updateElementClassProp(getStylingContext(index, viewData), stylingIndex, value ? true : false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1630,34 +1574,6 @@ export function elementStyling<T>(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the `StylingContext` at a given index.
|
||||
*
|
||||
* This method lazily creates the `StylingContext`. This is because in most cases
|
||||
* we have styling without any bindings. Creating `StylingContext` eagerly would mean that
|
||||
* every style declaration such as `<div style="color: red">` would result `StyleContext`
|
||||
* which would create unnecessary memory pressure.
|
||||
*
|
||||
* @param index Index of the style allocation. See: `elementStyling`.
|
||||
*/
|
||||
function getStylingContext(index: number): StylingContext {
|
||||
let slotValue = viewData[index + HEADER_OFFSET];
|
||||
|
||||
if (isLContainer(slotValue)) {
|
||||
const lContainer = slotValue;
|
||||
slotValue = lContainer[HOST_NATIVE];
|
||||
if (!Array.isArray(slotValue)) {
|
||||
return lContainer[HOST_NATIVE] =
|
||||
allocStylingContext(slotValue, getTNode(index).stylingTemplate !);
|
||||
}
|
||||
} else if (!Array.isArray(slotValue)) {
|
||||
// This is a regular ElementNode
|
||||
return viewData[index + HEADER_OFFSET] =
|
||||
allocStylingContext(slotValue, getTNode(index).stylingTemplate !);
|
||||
}
|
||||
|
||||
return slotValue as StylingContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply all styling values to the element which have been queued by any styling instructions.
|
||||
|
@ -1674,7 +1590,7 @@ function getStylingContext(index: number): StylingContext {
|
|||
* index.)
|
||||
*/
|
||||
export function elementStylingApply<T>(index: number): void {
|
||||
renderElementStyles(getStylingContext(index), renderer);
|
||||
renderElementStyles(getStylingContext(index, viewData), renderer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1713,7 +1629,7 @@ export function elementStyleProp<T>(
|
|||
valueToAdd = value as any as string;
|
||||
}
|
||||
}
|
||||
updateElementStyleProp(getStylingContext(index), styleIndex, valueToAdd);
|
||||
updateElementStyleProp(getStylingContext(index, viewData), styleIndex, valueToAdd);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1740,7 +1656,7 @@ export function elementStyleProp<T>(
|
|||
export function elementStylingMap<T>(
|
||||
index: number, classes: {[key: string]: any} | string | null,
|
||||
styles?: {[styleName: string]: any} | null): void {
|
||||
updateStylingMap(getStylingContext(index), classes, styles);
|
||||
updateStylingMap(getStylingContext(index, viewData), classes, styles);
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
|
@ -1800,11 +1716,12 @@ export function textBinding<T>(index: number, value: T | NO_CHANGE): void {
|
|||
*/
|
||||
export function directiveCreate<T>(
|
||||
directiveDefIdx: number, directive: T, directiveDef: DirectiveDef<T>| ComponentDef<T>): T {
|
||||
const hostNode = getLNode(previousOrParentTNode, viewData);
|
||||
const instance = baseDirectiveCreate(directiveDefIdx, directive, directiveDef, hostNode);
|
||||
const native = getNative(previousOrParentTNode, viewData);
|
||||
const instance = baseDirectiveCreate(directiveDefIdx, directive, directiveDef, native);
|
||||
|
||||
if ((directiveDef as ComponentDef<T>).template) {
|
||||
hostNode.data ![CONTEXT] = directive;
|
||||
const componentView = getComponentViewByIndex(previousOrParentTNode.index, viewData);
|
||||
componentView[CONTEXT] = directive;
|
||||
}
|
||||
|
||||
if (firstTemplatePass) {
|
||||
|
@ -1826,7 +1743,7 @@ export function directiveCreate<T>(
|
|||
}
|
||||
|
||||
function addComponentLogic<T>(def: ComponentDef<T>): void {
|
||||
const hostNode = getLNode(previousOrParentTNode, viewData);
|
||||
const native = getNative(previousOrParentTNode, viewData);
|
||||
|
||||
const tView = getOrCreateTView(
|
||||
def.template, def.consts, def.vars, def.directiveDefs, def.pipeDefs, def.viewQuery);
|
||||
|
@ -1836,13 +1753,15 @@ function addComponentLogic<T>(def: ComponentDef<T>): void {
|
|||
const componentView = addToViewTree(
|
||||
viewData, previousOrParentTNode.index as number,
|
||||
createLViewData(
|
||||
rendererFactory.createRenderer(hostNode.native as RElement, def), tView, null,
|
||||
rendererFactory.createRenderer(native as RElement, def), tView, null,
|
||||
def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways, getCurrentSanitizer()));
|
||||
|
||||
// We need to set the host node/data here because when the component LNode was created,
|
||||
// we didn't yet know it was a component (just an element).
|
||||
(hostNode as{data: LViewData}).data = componentView;
|
||||
(componentView as LViewData)[HOST_NODE] = previousOrParentTNode as TElementNode;
|
||||
componentView[HOST_NODE] = previousOrParentTNode as TElementNode;
|
||||
|
||||
// Component view will always be created before any injected LContainers,
|
||||
// so this is a regular LNode, wrap it with the component view
|
||||
componentView[HOST] = viewData[previousOrParentTNode.index];
|
||||
viewData[previousOrParentTNode.index] = componentView;
|
||||
|
||||
if (firstTemplatePass) {
|
||||
queueComponentIndexForCheck();
|
||||
|
@ -1859,15 +1778,15 @@ function addComponentLogic<T>(def: ComponentDef<T>): void {
|
|||
*/
|
||||
export function baseDirectiveCreate<T>(
|
||||
index: number, directive: T, directiveDef: DirectiveDef<T>| ComponentDef<T>,
|
||||
hostNode: LNode): T {
|
||||
native: RNode | null): T {
|
||||
ngDevMode && assertEqual(
|
||||
viewData[BINDING_INDEX], tView.bindingStartIndex,
|
||||
'directives should be created before any bindings');
|
||||
ngDevMode && assertPreviousIsParent();
|
||||
|
||||
attachPatchData(directive, viewData);
|
||||
if (hostNode) {
|
||||
attachPatchData(hostNode.native, viewData);
|
||||
if (native) {
|
||||
attachPatchData(native, viewData);
|
||||
}
|
||||
|
||||
viewData[index] = directive;
|
||||
|
@ -1897,7 +1816,7 @@ export function baseDirectiveCreate<T>(
|
|||
}
|
||||
|
||||
if (directiveDef !.attributes != null && previousOrParentTNode.type == TNodeType.Element) {
|
||||
setUpAttributes((hostNode as LElementNode).native, directiveDef !.attributes as string[]);
|
||||
setUpAttributes(native as RElement, directiveDef !.attributes as string[]);
|
||||
}
|
||||
|
||||
return directive;
|
||||
|
@ -1990,12 +1909,12 @@ export function createLContainer(
|
|||
native: RComment, isForViewContainerRef?: boolean): LContainer {
|
||||
return [
|
||||
isForViewContainerRef ? -1 : 0, // active index
|
||||
[], // views
|
||||
currentView, // parent
|
||||
null, // next
|
||||
null, // queries
|
||||
hostLNode, // host native
|
||||
native, // native
|
||||
[], // views
|
||||
getRenderParent(hostTNode, currentView) // renderParent
|
||||
];
|
||||
}
|
||||
|
@ -2269,11 +2188,8 @@ export function embeddedViewEnd(): void {
|
|||
export function componentRefresh<T>(
|
||||
adjustedElementIndex: number, parentFirstTemplatePass: boolean): void {
|
||||
ngDevMode && assertDataInRange(adjustedElementIndex);
|
||||
const element = readElementValue(viewData[adjustedElementIndex]) as LElementNode;
|
||||
const hostView = getComponentViewByIndex(adjustedElementIndex, viewData);
|
||||
ngDevMode && assertNodeType(tView.data[adjustedElementIndex] as TNode, TNodeType.Element);
|
||||
ngDevMode &&
|
||||
assertDefined(element.data, `Component's host node should have an LViewData attached.`);
|
||||
const hostView = element.data !;
|
||||
|
||||
// Only attached CheckAlways components or attached, dirty OnPush components should be checked
|
||||
if (viewAttached(hostView) && hostView[FLAGS] & (LViewFlags.CheckAlways | LViewFlags.Dirty)) {
|
||||
|
@ -2465,10 +2381,10 @@ export function addToViewTree<T extends LViewData|LContainer>(
|
|||
///////////////////////////////
|
||||
|
||||
/** If node is an OnPush component, marks its LViewData dirty. */
|
||||
export function markDirtyIfOnPush(node: LElementNode): void {
|
||||
// Because data flows down the component tree, ancestors do not need to be marked dirty
|
||||
if (node.data && !(node.data[FLAGS] & LViewFlags.CheckAlways)) {
|
||||
node.data[FLAGS] |= LViewFlags.Dirty;
|
||||
export function markDirtyIfOnPush(viewIndex: number): void {
|
||||
const view = getComponentViewByIndex(viewIndex, viewData);
|
||||
if (!(view[FLAGS] & LViewFlags.CheckAlways)) {
|
||||
view[FLAGS] |= LViewFlags.Dirty;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2576,10 +2492,7 @@ function tickRootContext(rootContext: RootContext) {
|
|||
* @param component The component which the change detection should be performed on.
|
||||
*/
|
||||
export function detectChanges<T>(component: T): void {
|
||||
const hostNode = getLElementFromComponent(component) !;
|
||||
ngDevMode &&
|
||||
assertDefined(hostNode, 'Component host node should be attached to an LViewData instance.');
|
||||
detectChangesInternal(hostNode.data !, component);
|
||||
detectChangesInternal(getComponentViewByInstance(component) !, component);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2673,8 +2586,7 @@ function updateViewQuery<T>(viewQuery: ComponentQuery<{}>| null, component: T):
|
|||
*/
|
||||
export function markDirty<T>(component: T) {
|
||||
ngDevMode && assertDefined(component, 'component');
|
||||
const elementNode = getLElementFromComponent(component) !;
|
||||
markViewDirty(elementNode.data as LViewData);
|
||||
markViewDirty(getComponentViewByInstance(component));
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
|
@ -2888,10 +2800,6 @@ export function loadElement(index: number): LElementNode {
|
|||
return loadElementInternal(index, viewData);
|
||||
}
|
||||
|
||||
export function getTNode(index: number): TNode {
|
||||
return tView.data[index + HEADER_OFFSET] as TNode;
|
||||
}
|
||||
|
||||
/** Gets the current binding value. */
|
||||
export function getBinding(bindingIndex: number): any {
|
||||
ngDevMode && assertDataInRange(viewData[bindingIndex]);
|
||||
|
|
|
@ -10,7 +10,8 @@ import {LContainerNode, LElementContainerNode, LElementNode} from './node';
|
|||
import {LQueries} from './query';
|
||||
import {RComment} from './renderer';
|
||||
import {StylingContext} from './styling';
|
||||
import {LViewData, NEXT, PARENT, QUERIES} from './view';
|
||||
import {HOST, LViewData, NEXT, PARENT, QUERIES} from './view';
|
||||
|
||||
|
||||
/**
|
||||
* Below are constants for LContainer indices to help us look up LContainer members
|
||||
|
@ -18,11 +19,10 @@ import {LViewData, NEXT, PARENT, QUERIES} from './view';
|
|||
* Uglify will inline these when minifying so there shouldn't be a cost.
|
||||
*/
|
||||
export const ACTIVE_INDEX = 0;
|
||||
// PARENT, NEXT, and QUERIES are indices 1, 2, and 3.
|
||||
export const VIEWS = 1;
|
||||
// PARENT, NEXT, QUERIES, and HOST are indices 2, 3, 4, and 5.
|
||||
// As we already have these constants in LViewData, we don't need to re-create them.
|
||||
export const HOST_NATIVE = 4;
|
||||
export const NATIVE = 5;
|
||||
export const VIEWS = 6;
|
||||
export const NATIVE = 6;
|
||||
export const RENDER_PARENT = 7;
|
||||
|
||||
/**
|
||||
|
@ -43,6 +43,15 @@ export interface LContainer extends Array<any> {
|
|||
*/
|
||||
[ACTIVE_INDEX]: number;
|
||||
|
||||
/**
|
||||
* A list of the container's currently active child views. Views will be inserted
|
||||
* here as they are added and spliced from here when they are removed. We need
|
||||
* to keep a record of current views so we know which views are already in the DOM
|
||||
* (and don't need to be re-added) and so we can remove views from the DOM when they
|
||||
* are no longer required.
|
||||
*/
|
||||
[VIEWS]: LViewData[];
|
||||
|
||||
/**
|
||||
* Access to the parent view is necessary so we can propagate back
|
||||
* up from inside a container to parent[NEXT].
|
||||
|
@ -63,20 +72,11 @@ export interface LContainer extends Array<any> {
|
|||
|
||||
/** The host node of this LContainer. */
|
||||
// TODO: Should contain just the native element once LNode is removed.
|
||||
[HOST_NATIVE]: LElementNode|LContainerNode|LElementContainerNode|StylingContext;
|
||||
[HOST]: LElementNode|LContainerNode|LElementContainerNode|StylingContext|LViewData;
|
||||
|
||||
/** The comment element that serves as an anchor for this LContainer. */
|
||||
[NATIVE]: RComment;
|
||||
|
||||
/**
|
||||
* A list of the container's currently active child views. Views will be inserted
|
||||
* here as they are added and spliced from here when they are removed. We need
|
||||
* to keep a record of current views so we know which views are already in the DOM
|
||||
* (and don't need to be re-added) and so we can remove views from the DOM when they
|
||||
* are no longer required.
|
||||
*/
|
||||
[VIEWS]: LViewData[];
|
||||
|
||||
/**
|
||||
* Parent Element which will contain the location where all of the Views will be
|
||||
* inserted into to.
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
|
||||
import {RElement} from './renderer';
|
||||
import {LViewData} from './view';
|
||||
|
||||
/**
|
||||
* This property will be monkey-patched on elements, components and directives
|
||||
*/
|
||||
export const MONKEY_PATCH_KEY_NAME = '__ngContext__';
|
||||
|
||||
/**
|
||||
* The internal view context which is specific to a given DOM element, directive or
|
||||
* component instance. Each value in here (besides the LViewData and element node details)
|
||||
* can be present, null or undefined. If undefined then it implies the value has not been
|
||||
* looked up yet, otherwise, if null, then a lookup was executed and nothing was found.
|
||||
*
|
||||
* Each value will get filled when the respective value is examined within the getContext
|
||||
* function. The component, element and each directive instance will share the same instance
|
||||
* of the context.
|
||||
*/
|
||||
export interface LContext {
|
||||
/**
|
||||
* The component's parent view data.
|
||||
*/
|
||||
lViewData: LViewData;
|
||||
|
||||
/**
|
||||
* The index instance of the node.
|
||||
*/
|
||||
nodeIndex: number;
|
||||
|
||||
/**
|
||||
* The instance of the DOM node that is attached to the lNode.
|
||||
*/
|
||||
native: RElement;
|
||||
|
||||
/**
|
||||
* The instance of the Component node.
|
||||
*/
|
||||
component: {}|null|undefined;
|
||||
|
||||
/**
|
||||
* The list of active directives that exist on this element.
|
||||
*/
|
||||
directives: any[]|null|undefined;
|
||||
|
||||
/**
|
||||
* The map of local references (local reference name => element or directive instance) that exist
|
||||
* on this element.
|
||||
*/
|
||||
localRefs: {[key: string]: any}|null|undefined;
|
||||
}
|
|
@ -69,14 +69,6 @@ export interface LNode {
|
|||
* - retrieve the sibling elements of text nodes whose creation / insertion has been delayed
|
||||
*/
|
||||
readonly native: RComment|RElement|RText|null;
|
||||
|
||||
/**
|
||||
* If regular LElementNode, LTextNode, LContainerNode, and LProjectionNode then `data` will be
|
||||
* null.
|
||||
* If LElementNode with component, then `data` contains LViewData.
|
||||
* If LViewNode, then `data` contains the LViewData.
|
||||
*/
|
||||
readonly data: LViewData|null;
|
||||
}
|
||||
|
||||
|
||||
|
@ -84,30 +76,22 @@ export interface LNode {
|
|||
export interface LElementNode extends LNode {
|
||||
/** The DOM element associated with this node. */
|
||||
readonly native: RElement;
|
||||
|
||||
/** If Component then data has LView (light DOM) */
|
||||
readonly data: LViewData|null;
|
||||
}
|
||||
|
||||
/** LNode representing <ng-container>. */
|
||||
export interface LElementContainerNode extends LNode {
|
||||
/** The DOM comment associated with this node. */
|
||||
readonly native: RComment;
|
||||
readonly data: null;
|
||||
}
|
||||
|
||||
/** LNode representing a #text node. */
|
||||
export interface LTextNode extends LNode {
|
||||
/** The text node associated with this node. */
|
||||
native: RText;
|
||||
readonly data: null;
|
||||
}
|
||||
|
||||
/** Abstract node which contains root nodes of a view. */
|
||||
export interface LViewNode extends LNode {
|
||||
readonly native: null;
|
||||
readonly data: LViewData;
|
||||
}
|
||||
export interface LViewNode extends LNode { readonly native: null; }
|
||||
|
||||
/** Abstract node container which contains other views. */
|
||||
export interface LContainerNode extends LNode {
|
||||
|
@ -119,14 +103,10 @@ export interface LContainerNode extends LNode {
|
|||
* until the parent view is processed.
|
||||
*/
|
||||
native: RComment;
|
||||
readonly data: null;
|
||||
}
|
||||
|
||||
|
||||
export interface LProjectionNode extends LNode {
|
||||
readonly native: null;
|
||||
readonly data: null;
|
||||
}
|
||||
export interface LProjectionNode extends LNode { readonly native: null; }
|
||||
|
||||
/**
|
||||
* A set of marker values to be used in the attributes arrays. Those markers indicate that some
|
||||
|
|
|
@ -121,11 +121,6 @@ import {PlayerContext} from './player';
|
|||
export interface StylingContext extends
|
||||
Array<InitialStyles|{[key: string]: any}|number|string|boolean|LElementNode|StyleSanitizeFn|
|
||||
PlayerContext|null> {
|
||||
/**
|
||||
* Location of element that is used as a target for this context.
|
||||
*/
|
||||
[StylingIndex.ElementPosition]: LElementNode|null;
|
||||
|
||||
/**
|
||||
* Location of animation context (which contains the active players) for this element styling
|
||||
* context.
|
||||
|
@ -156,6 +151,11 @@ export interface StylingContext extends
|
|||
*/
|
||||
[StylingIndex.ClassOffsetPosition]: number;
|
||||
|
||||
/**
|
||||
* Location of element that is used as a target for this context.
|
||||
*/
|
||||
[StylingIndex.ElementPosition]: LElementNode|null;
|
||||
|
||||
/**
|
||||
* The last class value that was interpreted by elementStylingMap. This is cached
|
||||
* So that the algorithm can exit early incase the value has not changed.
|
||||
|
@ -201,17 +201,18 @@ export const enum StylingFlags {
|
|||
/** Used as numeric pointer values to determine what cells to update in the `StylingContext` */
|
||||
export const enum StylingIndex {
|
||||
// Position of where the initial styles are stored in the styling context
|
||||
ElementPosition = 0,
|
||||
// Position of where the initial styles are stored in the styling context
|
||||
PlayerContext = 1,
|
||||
PlayerContext = 0,
|
||||
// Position of where the style sanitizer is stored within the styling context
|
||||
StyleSanitizerPosition = 2,
|
||||
StyleSanitizerPosition = 1,
|
||||
// Position of where the initial styles are stored in the styling context
|
||||
InitialStylesPosition = 3,
|
||||
InitialStylesPosition = 2,
|
||||
// Index of location where the start of single properties are stored. (`updateStyleProp`)
|
||||
MasterFlagPosition = 4,
|
||||
MasterFlagPosition = 3,
|
||||
// Index of location where the class index offset value is located
|
||||
ClassOffsetPosition = 5,
|
||||
ClassOffsetPosition = 4,
|
||||
// Position of where the initial styles are stored in the styling context
|
||||
// This index must align with HOST, see interfaces/view.ts
|
||||
ElementPosition = 5,
|
||||
// Position of where the last string-based CSS class value was stored
|
||||
PreviousMultiClassValue = 6,
|
||||
// Position of where the last string-based CSS class value was stored
|
||||
|
|
|
@ -13,32 +13,34 @@ import {PlayerHandler} from '../interfaces/player';
|
|||
|
||||
import {LContainer} from './container';
|
||||
import {ComponentDef, ComponentQuery, ComponentTemplate, DirectiveDef, DirectiveDefList, HostBindingsFunction, PipeDef, PipeDefList} from './definition';
|
||||
import {TElementNode, TNode, TViewNode} from './node';
|
||||
import {LContainerNode, LElementContainerNode, LElementNode, TElementNode, TNode, TViewNode} from './node';
|
||||
import {LQueries} from './query';
|
||||
import {Renderer3} from './renderer';
|
||||
import {StylingContext} from './styling';
|
||||
|
||||
/** Size of LViewData's header. Necessary to adjust for it when setting slots. */
|
||||
export const HEADER_OFFSET = 16;
|
||||
export const HEADER_OFFSET = 17;
|
||||
|
||||
// Below are constants for LViewData indices to help us look up LViewData members
|
||||
// without having to remember the specific indices.
|
||||
// Uglify will inline these when minifying so there shouldn't be a cost.
|
||||
export const TVIEW = 0;
|
||||
export const PARENT = 1;
|
||||
export const NEXT = 2;
|
||||
export const QUERIES = 3;
|
||||
export const FLAGS = 4;
|
||||
export const HOST_NODE = 5;
|
||||
export const BINDING_INDEX = 6;
|
||||
export const CLEANUP = 7;
|
||||
export const CONTEXT = 8;
|
||||
export const INJECTOR = 9;
|
||||
export const RENDERER = 10;
|
||||
export const SANITIZER = 11;
|
||||
export const TAIL = 12;
|
||||
export const CONTAINER_INDEX = 13;
|
||||
export const CONTENT_QUERIES = 14;
|
||||
export const DECLARATION_VIEW = 15;
|
||||
export const FLAGS = 1;
|
||||
export const PARENT = 2;
|
||||
export const NEXT = 3;
|
||||
export const QUERIES = 4;
|
||||
export const HOST = 5;
|
||||
export const HOST_NODE = 6;
|
||||
export const BINDING_INDEX = 7;
|
||||
export const CLEANUP = 8;
|
||||
export const CONTEXT = 9;
|
||||
export const INJECTOR = 10;
|
||||
export const RENDERER = 11;
|
||||
export const SANITIZER = 12;
|
||||
export const TAIL = 13;
|
||||
export const CONTAINER_INDEX = 14;
|
||||
export const CONTENT_QUERIES = 15;
|
||||
export const DECLARATION_VIEW = 16;
|
||||
|
||||
// This interface replaces the real LViewData interface if it is an arg or a
|
||||
// return value of a public instruction. This ensures we don't need to expose
|
||||
|
@ -66,6 +68,9 @@ export interface LViewData extends Array<any> {
|
|||
*/
|
||||
[TVIEW]: TView;
|
||||
|
||||
/** Flags for this view. See LViewFlags for more info. */
|
||||
[FLAGS]: LViewFlags;
|
||||
|
||||
/**
|
||||
* The parent view is needed when we exit the view and must restore the previous
|
||||
* `LViewData`. Without this, the render method would have to keep a stack of
|
||||
|
@ -90,8 +95,13 @@ export interface LViewData extends Array<any> {
|
|||
/** Queries active for this view - nodes from a view are reported to those queries. */
|
||||
[QUERIES]: LQueries|null;
|
||||
|
||||
/** Flags for this view. See LViewFlags for more info. */
|
||||
[FLAGS]: LViewFlags;
|
||||
/**
|
||||
* The host node for this LViewData instance, if this is a component view.
|
||||
*
|
||||
* If this is an embedded view, HOST will be null.
|
||||
*/
|
||||
// TODO: should store native elements directly when we remove LNode
|
||||
[HOST]: LElementNode|LContainerNode|LElementContainerNode|StylingContext|null;
|
||||
|
||||
/**
|
||||
* Pointer to the `TViewNode` or `TElementNode` which represents the root of the view.
|
||||
|
|
|
@ -7,16 +7,15 @@
|
|||
*/
|
||||
|
||||
import {assertDefined} from './assert';
|
||||
import {attachPatchData, readElementValue} from './context_discovery';
|
||||
import {attachPatchData} from './context_discovery';
|
||||
import {callHooks} from './hooks';
|
||||
import {HOST_NATIVE, LContainer, NATIVE, RENDER_PARENT, VIEWS, unusedValueExportToPlacateAjd as unused1} from './interfaces/container';
|
||||
import {LContainerNode, LElementContainerNode, LElementNode, LTextNode, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, TViewNode, unusedValueExportToPlacateAjd as unused2} from './interfaces/node';
|
||||
import {LContainer, NATIVE, RENDER_PARENT, VIEWS, unusedValueExportToPlacateAjd as unused1} from './interfaces/container';
|
||||
import {LContainerNode, LElementContainerNode, LElementNode, TContainerNode, TElementContainerNode, 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 {StylingIndex} from './interfaces/styling';
|
||||
import {CLEANUP, CONTAINER_INDEX, FLAGS, HEADER_OFFSET, HOST_NODE, HookData, LViewData, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, TVIEW, unusedValueExportToPlacateAjd as unused5} from './interfaces/view';
|
||||
import {assertNodeType} from './node_assert';
|
||||
import {getLNode, isLContainer, stringify} from './util';
|
||||
import {getLNode, getNative, isLContainer, readElementValue, stringify} from './util';
|
||||
|
||||
const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4 + unused5;
|
||||
|
||||
|
@ -104,8 +103,7 @@ function walkTNodeTree(
|
|||
let nextTNode: TNode|null = null;
|
||||
const parent = renderParentNode ? renderParentNode.native : null;
|
||||
if (tNode.type === TNodeType.Element) {
|
||||
const elementNode = getLNode(tNode, currentView);
|
||||
executeNodeAction(action, renderer, parent, elementNode.native !, beforeNode);
|
||||
executeNodeAction(action, renderer, parent, getNative(tNode, currentView), beforeNode);
|
||||
const nodeOrContainer = currentView[tNode.index];
|
||||
if (isLContainer(nodeOrContainer)) {
|
||||
// This element has an LContainer, and its comment needs to be handled
|
||||
|
@ -397,13 +395,7 @@ export function removeView(
|
|||
/** Gets the child of the given LViewData */
|
||||
export function getLViewChild(viewData: LViewData): LViewData|LContainer|null {
|
||||
const childIndex = viewData[TVIEW].childIndex;
|
||||
if (childIndex === -1) return null;
|
||||
|
||||
const value: LElementNode|LContainerNode|LContainer = viewData[childIndex];
|
||||
|
||||
// If it's an array, it's an LContainer. Otherwise, it's a component node, so LViewData
|
||||
// is stored in data.
|
||||
return Array.isArray(value) ? value : value.data;
|
||||
return childIndex === -1 ? null : viewData[childIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -668,7 +660,7 @@ export function getBeforeNodeForView(index: number, views: LViewData[], containe
|
|||
if (index + 1 < views.length) {
|
||||
const view = views[index + 1] as LViewData;
|
||||
const viewTNode = view[HOST_NODE] as TViewNode;
|
||||
return viewTNode.child ? getLNode(viewTNode.child, view).native : containerNative;
|
||||
return viewTNode.child ? getNative(viewTNode.child, view) : containerNative;
|
||||
} else {
|
||||
return containerNative;
|
||||
}
|
||||
|
@ -706,7 +698,7 @@ export function removeChild(tNode: TNode, child: RNode | null, currentView: LVie
|
|||
export function appendProjectedNode(
|
||||
projectedTNode: TNode, tProjectionNode: TNode, currentView: LViewData,
|
||||
projectionView: LViewData): void {
|
||||
const native = getLNode(projectedTNode, projectionView).native;
|
||||
const native = getNative(projectedTNode, projectionView);
|
||||
appendChild(native, tProjectionNode, currentView);
|
||||
|
||||
// the projected contents are processed while in the shadow view (which is the currentView)
|
||||
|
|
|
@ -14,21 +14,6 @@ import {InitialStyles, StylingContext, StylingFlags, StylingIndex} from '../inte
|
|||
|
||||
import {EMPTY_ARR, EMPTY_OBJ, createEmptyStylingContext} from './util';
|
||||
|
||||
|
||||
/**
|
||||
* Used clone a copy of a pre-computed template of a styling context.
|
||||
*
|
||||
* A pre-computed template is designed to be computed once for a given element
|
||||
* (instructions.ts has logic for caching this).
|
||||
*/
|
||||
export function allocStylingContext(
|
||||
lElement: LElementNode | null, templateStyleContext: StylingContext): StylingContext {
|
||||
// each instance gets a copy
|
||||
const context = templateStyleContext.slice() as any as StylingContext;
|
||||
context[StylingIndex.ElementPosition] = lElement;
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a styling context template where styling information is stored.
|
||||
* Any styles that are later referenced using `updateStyleProp` must be
|
||||
|
|
|
@ -5,11 +5,16 @@
|
|||
* 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
|
||||
*/
|
||||
|
||||
import {StyleSanitizeFn} from '../../sanitization/style_sanitizer';
|
||||
import {LContext, getContext} from '../context_discovery';
|
||||
import {getContext} from '../context_discovery';
|
||||
import {ACTIVE_INDEX, LContainer} from '../interfaces/container';
|
||||
import {LContext} from '../interfaces/context';
|
||||
import {LElementNode} from '../interfaces/node';
|
||||
import {PlayerContext} from '../interfaces/player';
|
||||
import {InitialStyles, StylingContext, StylingIndex} from '../interfaces/styling';
|
||||
import {FLAGS, HEADER_OFFSET, HOST, LViewData} from '../interfaces/view';
|
||||
import {getTNode} from '../util';
|
||||
|
||||
export const EMPTY_ARR: any[] = [];
|
||||
export const EMPTY_OBJ: {[key: string]: any} = {};
|
||||
|
@ -18,10 +23,70 @@ export function createEmptyStylingContext(
|
|||
element?: LElementNode | null, sanitizer?: StyleSanitizeFn | null,
|
||||
initialStylingValues?: InitialStyles): StylingContext {
|
||||
return [
|
||||
element || null, null, sanitizer || null, initialStylingValues || [null], 0, 0, null, null
|
||||
null, // PlayerContext
|
||||
sanitizer || null, // StyleSanitizer
|
||||
initialStylingValues || [null], // InitialStyles
|
||||
0, // MasterFlags
|
||||
0, // ClassOffset
|
||||
element || null, // Element
|
||||
null, // PreviousMultiClassValue
|
||||
null // PreviousMultiStyleValue
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Used clone a copy of a pre-computed template of a styling context.
|
||||
*
|
||||
* A pre-computed template is designed to be computed once for a given element
|
||||
* (instructions.ts has logic for caching this).
|
||||
*/
|
||||
export function allocStylingContext(
|
||||
lElement: LElementNode | null, templateStyleContext: StylingContext): StylingContext {
|
||||
// each instance gets a copy
|
||||
const context = templateStyleContext.slice() as any as StylingContext;
|
||||
context[StylingIndex.ElementPosition] = lElement;
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the `StylingContext` at a given index.
|
||||
*
|
||||
* This method lazily creates the `StylingContext`. This is because in most cases
|
||||
* we have styling without any bindings. Creating `StylingContext` eagerly would mean that
|
||||
* every style declaration such as `<div style="color: red">` would result `StyleContext`
|
||||
* which would create unnecessary memory pressure.
|
||||
*
|
||||
* @param index Index of the style allocation. See: `elementStyling`.
|
||||
* @param viewData The view to search for the styling context
|
||||
*/
|
||||
export function getStylingContext(index: number, viewData: LViewData): StylingContext {
|
||||
let storageIndex = index + HEADER_OFFSET;
|
||||
let slotValue: LContainer|LViewData|StylingContext|LElementNode = viewData[storageIndex];
|
||||
let wrapper: LContainer|LViewData|StylingContext = viewData;
|
||||
|
||||
while (Array.isArray(slotValue)) {
|
||||
wrapper = slotValue;
|
||||
slotValue = slotValue[HOST] as LViewData | StylingContext | LElementNode;
|
||||
}
|
||||
|
||||
if (isStylingContext(wrapper)) {
|
||||
return wrapper as StylingContext;
|
||||
} else {
|
||||
// This is an LViewData or an LContainer
|
||||
const stylingTemplate = getTNode(index, viewData).stylingTemplate;
|
||||
|
||||
if (wrapper !== viewData) storageIndex = HOST;
|
||||
return wrapper[storageIndex] = stylingTemplate ?
|
||||
allocStylingContext(slotValue, stylingTemplate) :
|
||||
createEmptyStylingContext(slotValue);
|
||||
}
|
||||
}
|
||||
|
||||
function isStylingContext(value: LViewData | LContainer | StylingContext) {
|
||||
// Not an LViewData or an LContainer
|
||||
return typeof value[FLAGS] !== 'number' && typeof value[ACTIVE_INDEX] !== 'number';
|
||||
}
|
||||
|
||||
export function getOrCreatePlayerContext(target: {}, context?: LContext | null): PlayerContext {
|
||||
context = context || getContext(target) !;
|
||||
if (ngDevMode && !context) {
|
||||
|
@ -30,11 +95,7 @@ export function getOrCreatePlayerContext(target: {}, context?: LContext | null):
|
|||
}
|
||||
|
||||
const {lViewData, nodeIndex} = context;
|
||||
const value = lViewData[nodeIndex];
|
||||
let stylingContext = value as StylingContext;
|
||||
if (!Array.isArray(value)) {
|
||||
stylingContext = lViewData[nodeIndex] = createEmptyStylingContext(value as LElementNode);
|
||||
}
|
||||
const stylingContext = getStylingContext(nodeIndex - HEADER_OFFSET, lViewData);
|
||||
return stylingContext[StylingIndex.PlayerContext] || allocPlayerContext(stylingContext);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,11 +9,12 @@
|
|||
import {devModeEqual} from '../change_detection/change_detection_util';
|
||||
|
||||
import {assertDefined, assertLessThan} from './assert';
|
||||
import {readElementValue, readPatchedLViewData} from './context_discovery';
|
||||
import {ACTIVE_INDEX, LContainer} from './interfaces/container';
|
||||
import {LContext, MONKEY_PATCH_KEY_NAME} from './interfaces/context';
|
||||
import {LContainerNode, LElementContainerNode, LElementNode, LNode, TNode, TNodeFlags} from './interfaces/node';
|
||||
import {RComment, RElement, RText} from './interfaces/renderer';
|
||||
import {StylingContext} from './interfaces/styling';
|
||||
import {CONTEXT, FLAGS, HEADER_OFFSET, LViewData, LViewFlags, PARENT, RootContext, TData, TVIEW} from './interfaces/view';
|
||||
import {CONTEXT, FLAGS, HEADER_OFFSET, HOST, LViewData, LViewFlags, PARENT, RootContext, TData, TVIEW, TView} from './interfaces/view';
|
||||
|
||||
|
||||
/**
|
||||
|
@ -92,11 +93,45 @@ export function loadElementInternal(index: number, arr: LViewData): LElementNode
|
|||
return readElementValue(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the value of a slot in `LViewData` and returns the element node.
|
||||
*
|
||||
* Normally, element nodes are stored flat, but if the node has styles/classes on it,
|
||||
* it might be wrapped in a styling context. Or if that node has a directive that injects
|
||||
* ViewContainerRef, it may be wrapped in an LContainer. Or if that node is a component,
|
||||
* it will be wrapped in LViewData. It could even have all three, so we keep looping
|
||||
* until we find something that isn't an array.
|
||||
*
|
||||
* @param value The initial value in `LViewData`
|
||||
*/
|
||||
export function readElementValue(value: LElementNode | StylingContext | LContainer | LViewData):
|
||||
LElementNode {
|
||||
while (Array.isArray(value)) {
|
||||
value = value[HOST] as any;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export function getNative(tNode: TNode, hostView: LViewData): RElement|RText|RComment {
|
||||
return getLNode(tNode, hostView).native;
|
||||
}
|
||||
|
||||
// TODO(kara): remove when removing LNode.native
|
||||
export function getLNode(tNode: TNode, hostView: LViewData): LElementNode|LContainerNode|
|
||||
LElementContainerNode {
|
||||
return readElementValue(hostView[tNode.index]);
|
||||
}
|
||||
|
||||
export function getTNode(index: number, view: LViewData): TNode {
|
||||
return view[TVIEW].data[index + HEADER_OFFSET] as TNode;
|
||||
}
|
||||
|
||||
export function getComponentViewByIndex(nodeIndex: number, hostView: LViewData): LViewData {
|
||||
// Could be an LViewData or an LContainer. If LContainer, unwrap to find LViewData.
|
||||
const slotValue = hostView[nodeIndex];
|
||||
return slotValue.length >= HEADER_OFFSET ? slotValue : slotValue[HOST];
|
||||
}
|
||||
|
||||
export function isContentQueryHost(tNode: TNode): boolean {
|
||||
return (tNode.flags & TNodeFlags.hasContentQuery) !== 0;
|
||||
}
|
||||
|
@ -128,3 +163,19 @@ export function getRootView(target: LViewData | {}): LViewData {
|
|||
export function getRootContext(viewOrComponent: LViewData | {}): RootContext {
|
||||
return getRootView(viewOrComponent)[CONTEXT] as RootContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the monkey-patch value data present on the target (which could be
|
||||
* a component, directive or a DOM node).
|
||||
*/
|
||||
export function readPatchedData(target: any): LViewData|LContext|null {
|
||||
return target[MONKEY_PATCH_KEY_NAME];
|
||||
}
|
||||
|
||||
export function readPatchedLViewData(target: any): LViewData|null {
|
||||
const value = readPatchedData(target);
|
||||
if (value) {
|
||||
return Array.isArray(value) ? value : (value as LContext).lViewData;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ import {RComment, RElement, Renderer3, isProceduralRenderer} from './interfaces/
|
|||
import {CONTEXT, HOST_NODE, LViewData, QUERIES, RENDERER, TVIEW, TView} from './interfaces/view';
|
||||
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
|
||||
import {addRemoveViewFromContainer, appendChild, detachView, findComponentView, getBeforeNodeForView, getRenderParent, insertView, removeView} from './node_manipulation';
|
||||
import {getLNode, isComponent, isLContainer} from './util';
|
||||
import {getComponentViewByIndex, getNative, isComponent, isLContainer} from './util';
|
||||
import {ViewRef} from './view_ref';
|
||||
|
||||
|
||||
|
@ -60,7 +60,7 @@ export function createElementRef(
|
|||
// TODO: Fix class name, should be ElementRef, but there appears to be a rollup bug
|
||||
R3ElementRef = class ElementRef_ extends ElementRefToken {};
|
||||
}
|
||||
return new R3ElementRef(getLNode(tNode, view).native);
|
||||
return new R3ElementRef(getNative(tNode, view));
|
||||
}
|
||||
|
||||
let R3TemplateRef: {
|
||||
|
@ -325,7 +325,7 @@ export function createViewRef(
|
|||
hostTNode: TNode, hostView: LViewData, context: any): ViewEngine_ChangeDetectorRef {
|
||||
if (isComponent(hostTNode)) {
|
||||
const componentIndex = hostTNode.flags >> TNodeFlags.DirectiveStartingIndexShift;
|
||||
const componentView = getLNode(hostTNode, hostView).data as LViewData;
|
||||
const componentView = getComponentViewByIndex(hostTNode.index, hostView);
|
||||
return new ViewRef(componentView, context, componentIndex);
|
||||
} else if (hostTNode.type === TNodeType.Element) {
|
||||
const hostComponentView = findComponentView(hostView);
|
||||
|
@ -346,4 +346,4 @@ function getOrCreateRenderer2(view: LViewData): Renderer2 {
|
|||
/** Returns a Renderer2 (or throws when application was bootstrapped with Renderer3) */
|
||||
export function injectRenderer2(): Renderer2 {
|
||||
return getOrCreateRenderer2(_getViewData());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
"name": "HEADER_OFFSET"
|
||||
},
|
||||
{
|
||||
"name": "HOST_NATIVE"
|
||||
"name": "HOST"
|
||||
},
|
||||
{
|
||||
"name": "HOST_NODE"
|
||||
|
@ -374,9 +374,6 @@
|
|||
{
|
||||
"name": "createLContext"
|
||||
},
|
||||
{
|
||||
"name": "createLNodeObject"
|
||||
},
|
||||
{
|
||||
"name": "createLViewData"
|
||||
},
|
||||
|
@ -389,6 +386,9 @@
|
|||
{
|
||||
"name": "createRootComponent"
|
||||
},
|
||||
{
|
||||
"name": "createRootComponentView"
|
||||
},
|
||||
{
|
||||
"name": "createRootContext"
|
||||
},
|
||||
|
@ -551,6 +551,12 @@
|
|||
{
|
||||
"name": "getComponentDef"
|
||||
},
|
||||
{
|
||||
"name": "getComponentViewByIndex"
|
||||
},
|
||||
{
|
||||
"name": "getComponentViewByInstance"
|
||||
},
|
||||
{
|
||||
"name": "getContainerRenderParent"
|
||||
},
|
||||
|
@ -590,9 +596,6 @@
|
|||
{
|
||||
"name": "getLContainer"
|
||||
},
|
||||
{
|
||||
"name": "getLElementFromComponent"
|
||||
},
|
||||
{
|
||||
"name": "getLNode"
|
||||
},
|
||||
|
@ -608,6 +611,9 @@
|
|||
{
|
||||
"name": "getMultiStartIndex"
|
||||
},
|
||||
{
|
||||
"name": "getNative"
|
||||
},
|
||||
{
|
||||
"name": "getOrCreateInjectable"
|
||||
},
|
||||
|
@ -644,9 +650,6 @@
|
|||
{
|
||||
"name": "getPreviousIndex"
|
||||
},
|
||||
{
|
||||
"name": "getPreviousOrParentNode"
|
||||
},
|
||||
{
|
||||
"name": "getPreviousOrParentTNode"
|
||||
},
|
||||
|
@ -698,9 +701,6 @@
|
|||
{
|
||||
"name": "hasValueChanged"
|
||||
},
|
||||
{
|
||||
"name": "hostElement"
|
||||
},
|
||||
{
|
||||
"name": "inject"
|
||||
},
|
||||
|
@ -734,6 +734,9 @@
|
|||
{
|
||||
"name": "isClassBased"
|
||||
},
|
||||
{
|
||||
"name": "isComponent"
|
||||
},
|
||||
{
|
||||
"name": "isComponentInstance"
|
||||
},
|
||||
|
@ -782,6 +785,9 @@
|
|||
{
|
||||
"name": "isSanitizable"
|
||||
},
|
||||
{
|
||||
"name": "isStylingContext"
|
||||
},
|
||||
{
|
||||
"name": "iterateListLike"
|
||||
},
|
||||
|
@ -824,9 +830,6 @@
|
|||
{
|
||||
"name": "nativeInsertBefore"
|
||||
},
|
||||
{
|
||||
"name": "nativeNodeLocalRefExtractor"
|
||||
},
|
||||
{
|
||||
"name": "nextContext"
|
||||
},
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
"name": "HEADER_OFFSET"
|
||||
},
|
||||
{
|
||||
"name": "HOST_NATIVE"
|
||||
"name": "HOST"
|
||||
},
|
||||
{
|
||||
"name": "HOST_NODE"
|
||||
|
@ -155,9 +155,6 @@
|
|||
{
|
||||
"name": "componentRefresh"
|
||||
},
|
||||
{
|
||||
"name": "createLNodeObject"
|
||||
},
|
||||
{
|
||||
"name": "createLViewData"
|
||||
},
|
||||
|
@ -167,6 +164,9 @@
|
|||
{
|
||||
"name": "createRootComponent"
|
||||
},
|
||||
{
|
||||
"name": "createRootComponentView"
|
||||
},
|
||||
{
|
||||
"name": "createRootContext"
|
||||
},
|
||||
|
@ -230,6 +230,9 @@
|
|||
{
|
||||
"name": "getComponentDef"
|
||||
},
|
||||
{
|
||||
"name": "getComponentViewByIndex"
|
||||
},
|
||||
{
|
||||
"name": "getContainerRenderParent"
|
||||
},
|
||||
|
@ -254,6 +257,9 @@
|
|||
{
|
||||
"name": "getLViewChild"
|
||||
},
|
||||
{
|
||||
"name": "getNative"
|
||||
},
|
||||
{
|
||||
"name": "getOrCreateNodeInjector"
|
||||
},
|
||||
|
@ -284,9 +290,6 @@
|
|||
{
|
||||
"name": "getRenderParent"
|
||||
},
|
||||
{
|
||||
"name": "hostElement"
|
||||
},
|
||||
{
|
||||
"name": "invertObject"
|
||||
},
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
"name": "HEADER_OFFSET"
|
||||
},
|
||||
{
|
||||
"name": "HOST_NATIVE"
|
||||
"name": "HOST"
|
||||
},
|
||||
{
|
||||
"name": "HOST_NODE"
|
||||
|
@ -437,9 +437,6 @@
|
|||
{
|
||||
"name": "createLContext"
|
||||
},
|
||||
{
|
||||
"name": "createLNodeObject"
|
||||
},
|
||||
{
|
||||
"name": "createLViewData"
|
||||
},
|
||||
|
@ -452,6 +449,9 @@
|
|||
{
|
||||
"name": "createRootComponent"
|
||||
},
|
||||
{
|
||||
"name": "createRootComponentView"
|
||||
},
|
||||
{
|
||||
"name": "createRootContext"
|
||||
},
|
||||
|
@ -602,6 +602,12 @@
|
|||
{
|
||||
"name": "getComponentDef"
|
||||
},
|
||||
{
|
||||
"name": "getComponentViewByIndex"
|
||||
},
|
||||
{
|
||||
"name": "getComponentViewByInstance"
|
||||
},
|
||||
{
|
||||
"name": "getContainerRenderParent"
|
||||
},
|
||||
|
@ -635,9 +641,6 @@
|
|||
{
|
||||
"name": "getLContainer"
|
||||
},
|
||||
{
|
||||
"name": "getLElementFromComponent"
|
||||
},
|
||||
{
|
||||
"name": "getLNode"
|
||||
},
|
||||
|
@ -650,6 +653,9 @@
|
|||
{
|
||||
"name": "getMultiStartIndex"
|
||||
},
|
||||
{
|
||||
"name": "getNative"
|
||||
},
|
||||
{
|
||||
"name": "getOrCreateInjectable"
|
||||
},
|
||||
|
@ -683,9 +689,6 @@
|
|||
{
|
||||
"name": "getPreviousIndex"
|
||||
},
|
||||
{
|
||||
"name": "getPreviousOrParentNode"
|
||||
},
|
||||
{
|
||||
"name": "getPreviousOrParentTNode"
|
||||
},
|
||||
|
@ -731,9 +734,6 @@
|
|||
{
|
||||
"name": "hasValueChanged"
|
||||
},
|
||||
{
|
||||
"name": "hostElement"
|
||||
},
|
||||
{
|
||||
"name": "inject"
|
||||
},
|
||||
|
@ -761,6 +761,9 @@
|
|||
{
|
||||
"name": "invertObject"
|
||||
},
|
||||
{
|
||||
"name": "isComponent"
|
||||
},
|
||||
{
|
||||
"name": "isContentQueryHost"
|
||||
},
|
||||
|
@ -800,6 +803,9 @@
|
|||
{
|
||||
"name": "isProceduralRenderer"
|
||||
},
|
||||
{
|
||||
"name": "isStylingContext"
|
||||
},
|
||||
{
|
||||
"name": "iterateListLike"
|
||||
},
|
||||
|
@ -845,9 +851,6 @@
|
|||
{
|
||||
"name": "nativeInsertBefore"
|
||||
},
|
||||
{
|
||||
"name": "nativeNodeLocalRefExtractor"
|
||||
},
|
||||
{
|
||||
"name": "nextContext"
|
||||
},
|
||||
|
|
|
@ -321,10 +321,10 @@
|
|||
"name": "HEADER_OFFSET"
|
||||
},
|
||||
{
|
||||
"name": "HOST_ATTR$1"
|
||||
"name": "HOST"
|
||||
},
|
||||
{
|
||||
"name": "HOST_NATIVE"
|
||||
"name": "HOST_ATTR$1"
|
||||
},
|
||||
{
|
||||
"name": "HOST_NODE"
|
||||
|
@ -1319,9 +1319,6 @@
|
|||
{
|
||||
"name": "createLContext"
|
||||
},
|
||||
{
|
||||
"name": "createLNodeObject"
|
||||
},
|
||||
{
|
||||
"name": "createLViewData"
|
||||
},
|
||||
|
@ -1340,6 +1337,9 @@
|
|||
{
|
||||
"name": "createRootComponent"
|
||||
},
|
||||
{
|
||||
"name": "createRootComponentView"
|
||||
},
|
||||
{
|
||||
"name": "createRootContext"
|
||||
},
|
||||
|
@ -1610,6 +1610,12 @@
|
|||
{
|
||||
"name": "getComponentDef"
|
||||
},
|
||||
{
|
||||
"name": "getComponentViewByIndex"
|
||||
},
|
||||
{
|
||||
"name": "getComponentViewByInstance"
|
||||
},
|
||||
{
|
||||
"name": "getContainerRenderParent"
|
||||
},
|
||||
|
@ -1673,9 +1679,6 @@
|
|||
{
|
||||
"name": "getLContainer"
|
||||
},
|
||||
{
|
||||
"name": "getLElementFromComponent"
|
||||
},
|
||||
{
|
||||
"name": "getLNode"
|
||||
},
|
||||
|
@ -1736,6 +1739,9 @@
|
|||
{
|
||||
"name": "getNamedFormat"
|
||||
},
|
||||
{
|
||||
"name": "getNative"
|
||||
},
|
||||
{
|
||||
"name": "getNgModuleDef"
|
||||
},
|
||||
|
@ -1793,9 +1799,6 @@
|
|||
{
|
||||
"name": "getPreviousIndex"
|
||||
},
|
||||
{
|
||||
"name": "getPreviousOrParentNode"
|
||||
},
|
||||
{
|
||||
"name": "getPreviousOrParentTNode"
|
||||
},
|
||||
|
@ -1865,9 +1868,6 @@
|
|||
{
|
||||
"name": "hasValueChanged"
|
||||
},
|
||||
{
|
||||
"name": "hostElement"
|
||||
},
|
||||
{
|
||||
"name": "hostReportError"
|
||||
},
|
||||
|
@ -2018,6 +2018,9 @@
|
|||
{
|
||||
"name": "isScheduler"
|
||||
},
|
||||
{
|
||||
"name": "isStylingContext"
|
||||
},
|
||||
{
|
||||
"name": "isTemplateElement"
|
||||
},
|
||||
|
@ -2111,9 +2114,6 @@
|
|||
{
|
||||
"name": "nativeInsertBefore"
|
||||
},
|
||||
{
|
||||
"name": "nativeNodeLocalRefExtractor"
|
||||
},
|
||||
{
|
||||
"name": "nextContext"
|
||||
},
|
||||
|
|
|
@ -6,17 +6,18 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {TemplateRef, ViewContainerRef} from '@angular/core';
|
||||
import {withBody} from '@angular/private/testing';
|
||||
|
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, DoCheck, RendererType2} from '../../src/core';
|
||||
import {getRenderedText, whenRendered} from '../../src/render3/component';
|
||||
import {directiveInject} from '../../src/render3/di';
|
||||
import {LifecycleHooksFeature, defineComponent, defineDirective} from '../../src/render3/index';
|
||||
import {bind, container, containerRefreshEnd, containerRefreshStart, detectChanges, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation2, listener, markDirty, text, textBinding, tick} from '../../src/render3/instructions';
|
||||
import {LifecycleHooksFeature, defineComponent, defineDirective, templateRefExtractor} from '../../src/render3/index';
|
||||
import {bind, container, containerRefreshEnd, containerRefreshStart, detectChanges, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation2, listener, markDirty, reference, text, template, textBinding, tick} from '../../src/render3/instructions';
|
||||
import {RenderFlags} from '../../src/render3/interfaces/definition';
|
||||
import {RElement, Renderer3, RendererFactory3} from '../../src/render3/interfaces/renderer';
|
||||
|
||||
import {containerEl, createComponent, renderComponent, requestAnimationFrame} from './render_util';
|
||||
import {ComponentFixture, containerEl, createComponent, renderComponent, requestAnimationFrame} from './render_util';
|
||||
|
||||
describe('change detection', () => {
|
||||
describe('markDirty, detectChanges, whenRendered, getRenderedText', () => {
|
||||
|
@ -86,6 +87,73 @@ describe('change detection', () => {
|
|||
await whenRendered(myComp);
|
||||
expect(getRenderedText(myComp)).toEqual('updated');
|
||||
}));
|
||||
|
||||
it('should support detectChanges on components that have LContainers', () => {
|
||||
let structuralComp !: StructuralComp;
|
||||
|
||||
class StructuralComp {
|
||||
tmp !: TemplateRef<any>;
|
||||
value = 'one';
|
||||
|
||||
constructor(public vcr: ViewContainerRef) {}
|
||||
|
||||
create() { this.vcr.createEmbeddedView(this.tmp); }
|
||||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: StructuralComp,
|
||||
selectors: [['structural-comp']],
|
||||
factory: () => structuralComp =
|
||||
new StructuralComp(directiveInject(ViewContainerRef as any)),
|
||||
inputs: {tmp: 'tmp'},
|
||||
consts: 1,
|
||||
vars: 1,
|
||||
template: (rf: RenderFlags, ctx: StructuralComp) => {
|
||||
if (rf & RenderFlags.Create) {
|
||||
text(0);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
textBinding(0, bind(ctx.value));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function FooTemplate(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
text(0, 'Temp content');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <ng-template #foo>
|
||||
* Temp content
|
||||
* </ng-template>
|
||||
* <structural-comp [tmp]="foo"></structural-comp>
|
||||
*/
|
||||
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
template(0, FooTemplate, 1, 0, '', null, ['foo', ''], templateRefExtractor);
|
||||
element(2, 'structural-comp');
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
const foo = reference(1) as any;
|
||||
elementProperty(2, 'tmp', bind(foo));
|
||||
}
|
||||
}, 3, 1, [StructuralComp]);
|
||||
|
||||
const fixture = new ComponentFixture(App);
|
||||
fixture.update();
|
||||
expect(fixture.html).toEqual('<structural-comp>one</structural-comp>');
|
||||
|
||||
structuralComp.create();
|
||||
fixture.update();
|
||||
expect(fixture.html).toEqual('<structural-comp>one</structural-comp>Temp content');
|
||||
|
||||
structuralComp.value = 'two';
|
||||
detectChanges(structuralComp);
|
||||
expect(fixture.html).toEqual('<structural-comp>two</structural-comp>Temp content');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('onPush', () => {
|
||||
|
|
|
@ -81,7 +81,7 @@ describe('instructions', () => {
|
|||
element(0, 'div', ['id', 'test', 'title', 'Hello']);
|
||||
}, () => {}, 1);
|
||||
|
||||
const div = (t.hostNode.native as HTMLElement).querySelector('div') !;
|
||||
const div = (t.hostElement as HTMLElement).querySelector('div') !;
|
||||
expect(div.id).toEqual('test');
|
||||
expect(div.title).toEqual('Hello');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
|
@ -109,7 +109,7 @@ describe('instructions', () => {
|
|||
]);
|
||||
}, () => {}, 1);
|
||||
|
||||
const div = (t.hostNode.native as HTMLElement).querySelector('div') !;
|
||||
const div = (t.hostElement as HTMLElement).querySelector('div') !;
|
||||
const attrs: any = div.attributes;
|
||||
|
||||
expect(attrs['id'].name).toEqual('id');
|
||||
|
@ -179,7 +179,7 @@ describe('instructions', () => {
|
|||
|
||||
t.update(() => elementProperty(0, 'hidden', false));
|
||||
// The hidden property would be true if `false` was stringified into `"false"`.
|
||||
expect((t.hostNode.native as HTMLElement).querySelector('div') !.hidden).toEqual(false);
|
||||
expect((t.hostElement as HTMLElement).querySelector('div') !.hidden).toEqual(false);
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
|
|
|
@ -20,8 +20,9 @@ import {Sanitizer, SecurityContext} from '../../src/sanitization/security';
|
|||
|
||||
import {NgIf} from './common_with_def';
|
||||
import {ComponentFixture, TemplateFixture, createComponent, renderToHtml} from './render_util';
|
||||
import {MONKEY_PATCH_KEY_NAME, getContext} from '../../src/render3/context_discovery';
|
||||
import {getContext} from '../../src/render3/context_discovery';
|
||||
import {StylingIndex} from '../../src/render3/interfaces/styling';
|
||||
import {MONKEY_PATCH_KEY_NAME} from '../../src/render3/interfaces/context';
|
||||
import {directiveInject} from '../../src/render3/di';
|
||||
|
||||
describe('render3 integration test', () => {
|
||||
|
@ -1414,6 +1415,39 @@ describe('render3 integration test', () => {
|
|||
expect(fixture.html).toEqual('<span class="existing"></span>');
|
||||
});
|
||||
|
||||
it('should apply classes properly when nodes are components', () => {
|
||||
const MyComp = createComponent('my-comp', (rf: RenderFlags, ctx: any) => {
|
||||
if (rf & RenderFlags.Create) {
|
||||
text(0, 'Comp Content');
|
||||
}
|
||||
}, 1, 0, []);
|
||||
|
||||
/**
|
||||
* <my-comp [class.active]="class"></my-comp>
|
||||
*/
|
||||
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
elementStart(0, 'my-comp');
|
||||
{ elementStyling(['active']); }
|
||||
elementEnd();
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementClassProp(0, 0, ctx.class);
|
||||
elementStylingApply(0);
|
||||
}
|
||||
}, 1, 0, [MyComp]);
|
||||
|
||||
const fixture = new ComponentFixture(App);
|
||||
fixture.component.class = true;
|
||||
fixture.update();
|
||||
expect(fixture.html).toEqual('<my-comp class="active">Comp Content</my-comp>');
|
||||
|
||||
fixture.component.class = false;
|
||||
fixture.update();
|
||||
expect(fixture.html).toEqual('<my-comp class="">Comp Content</my-comp>');
|
||||
});
|
||||
|
||||
|
||||
it('should apply classes properly when nodes have LContainers', () => {
|
||||
let structuralComp !: StructuralComp;
|
||||
|
||||
|
@ -1448,7 +1482,7 @@ describe('render3 integration test', () => {
|
|||
|
||||
/**
|
||||
* <ng-template #foo>
|
||||
* Content
|
||||
* Temp Content
|
||||
* </ng-template>
|
||||
* <structural-comp [class.active]="class" [tmp]="foo"></structural-comp>
|
||||
*/
|
||||
|
@ -1477,8 +1511,12 @@ describe('render3 integration test', () => {
|
|||
fixture.update();
|
||||
expect(fixture.html)
|
||||
.toEqual('<structural-comp class="active">Comp Content</structural-comp>Temp Content');
|
||||
});
|
||||
|
||||
fixture.component.class = false;
|
||||
fixture.update();
|
||||
expect(fixture.html)
|
||||
.toEqual('<structural-comp class="">Comp Content</structural-comp>Temp Content');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -2168,12 +2206,11 @@ describe('render3 integration test', () => {
|
|||
const div1 = hostElm.querySelector('div:first-child') !as any;
|
||||
const div2 = hostElm.querySelector('div:last-child') !as any;
|
||||
const context = getContext(hostElm) !;
|
||||
const elementNode = context.lViewData[context.nodeIndex];
|
||||
const elmData = elementNode.data !;
|
||||
const componentView = context.lViewData[context.nodeIndex];
|
||||
|
||||
expect(elmData).toContain(myDir1Instance);
|
||||
expect(elmData).toContain(myDir2Instance);
|
||||
expect(elmData).toContain(myDir3Instance);
|
||||
expect(componentView).toContain(myDir1Instance);
|
||||
expect(componentView).toContain(myDir2Instance);
|
||||
expect(componentView).toContain(myDir3Instance);
|
||||
|
||||
expect(Array.isArray((myDir1Instance as any)[MONKEY_PATCH_KEY_NAME])).toBeTruthy();
|
||||
expect(Array.isArray((myDir2Instance as any)[MONKEY_PATCH_KEY_NAME])).toBeTruthy();
|
||||
|
@ -2183,9 +2220,9 @@ describe('render3 integration test', () => {
|
|||
const d2Context = getContext(myDir2Instance) !;
|
||||
const d3Context = getContext(myDir3Instance) !;
|
||||
|
||||
expect(d1Context.lViewData).toEqual(elmData);
|
||||
expect(d2Context.lViewData).toEqual(elmData);
|
||||
expect(d3Context.lViewData).toEqual(elmData);
|
||||
expect(d1Context.lViewData).toEqual(componentView);
|
||||
expect(d2Context.lViewData).toEqual(componentView);
|
||||
expect(d3Context.lViewData).toEqual(componentView);
|
||||
|
||||
expect((myDir1Instance as any)[MONKEY_PATCH_KEY_NAME]).toBe(d1Context);
|
||||
expect((myDir2Instance as any)[MONKEY_PATCH_KEY_NAME]).toBe(d2Context);
|
||||
|
@ -2349,7 +2386,7 @@ describe('render3 integration test', () => {
|
|||
const context = getContext(child) !;
|
||||
expect(child[MONKEY_PATCH_KEY_NAME]).toBeTruthy();
|
||||
|
||||
const componentData = context.lViewData[context.nodeIndex].data;
|
||||
const componentData = context.lViewData[context.nodeIndex];
|
||||
const component = componentData[CONTEXT];
|
||||
expect(component instanceof ChildComp).toBeTruthy();
|
||||
expect(component[MONKEY_PATCH_KEY_NAME]).toBe(context.lViewData);
|
||||
|
|
|
@ -25,7 +25,7 @@ import {DirectiveDefList, DirectiveTypesOrFactory, PipeDef, PipeDefList, PipeTyp
|
|||
import {LElementNode} from '../../src/render3/interfaces/node';
|
||||
import {PlayerHandler} from '../../src/render3/interfaces/player';
|
||||
import {RElement, RText, Renderer3, RendererFactory3, domRendererFactory3} from '../../src/render3/interfaces/renderer';
|
||||
import {HEADER_OFFSET} from '../../src/render3/interfaces/view';
|
||||
import {HEADER_OFFSET, LViewData} from '../../src/render3/interfaces/view';
|
||||
import {Sanitizer} from '../../src/sanitization/security';
|
||||
import {Type} from '../../src/type';
|
||||
|
||||
|
@ -55,7 +55,7 @@ function noop() {}
|
|||
* - access to the render `html`.
|
||||
*/
|
||||
export class TemplateFixture extends BaseFixture {
|
||||
hostNode: LElementNode;
|
||||
hostView: LViewData;
|
||||
private _directiveDefs: DirectiveDefList|null;
|
||||
private _pipeDefs: PipeDefList|null;
|
||||
private _sanitizer: Sanitizer|null;
|
||||
|
@ -78,7 +78,7 @@ export class TemplateFixture extends BaseFixture {
|
|||
this._pipeDefs = toDefs(pipes, extractPipeDef);
|
||||
this._sanitizer = sanitizer || null;
|
||||
this._rendererFactory = rendererFactory || domRendererFactory3;
|
||||
this.hostNode = renderTemplate(
|
||||
this.hostView = renderTemplate(
|
||||
this.hostElement,
|
||||
(rf: RenderFlags, ctx: any) => {
|
||||
if (rf & RenderFlags.Create) {
|
||||
|
@ -99,8 +99,8 @@ export class TemplateFixture extends BaseFixture {
|
|||
*/
|
||||
update(updateBlock?: () => void): void {
|
||||
renderTemplate(
|
||||
this.hostNode.native, updateBlock || this.updateBlock, 0, this.vars, null !,
|
||||
this._rendererFactory, this.hostNode, this._directiveDefs, this._pipeDefs, this._sanitizer);
|
||||
this.hostElement, updateBlock || this.updateBlock, 0, this.vars, null !,
|
||||
this._rendererFactory, this.hostView, this._directiveDefs, this._pipeDefs, this._sanitizer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,7 @@ export class ComponentFixture<T> extends BaseFixture {
|
|||
|
||||
export const document = ((typeof global == 'object' && global || window) as any).document;
|
||||
export let containerEl: HTMLElement = null !;
|
||||
let host: LElementNode|null;
|
||||
let hostView: LViewData|null;
|
||||
const isRenderer2 =
|
||||
typeof process == 'object' && process.argv[3] && process.argv[3] === '--r=renderer2';
|
||||
// tslint:disable-next-line:no-console
|
||||
|
@ -181,7 +181,7 @@ export function resetDOM() {
|
|||
containerEl = document.createElement('div');
|
||||
containerEl.setAttribute('host', '');
|
||||
document.body.appendChild(containerEl);
|
||||
host = null;
|
||||
hostView = null;
|
||||
// TODO: assert that the global state is clean (e.g. ngData, previousOrParentNode, etc)
|
||||
}
|
||||
|
||||
|
@ -192,9 +192,9 @@ export function renderToHtml(
|
|||
template: ComponentTemplate<any>, ctx: any, consts: number = 0, vars: number = 0,
|
||||
directives?: DirectiveTypesOrFactory | null, pipes?: PipeTypesOrFactory | null,
|
||||
providedRendererFactory?: RendererFactory3 | null) {
|
||||
host = renderTemplate(
|
||||
hostView = renderTemplate(
|
||||
containerEl, template, consts, vars, ctx, providedRendererFactory || testRendererFactory,
|
||||
host, toDefs(directives, extractDirectiveDef), toDefs(pipes, extractPipeDef));
|
||||
hostView, toDefs(directives, extractDirectiveDef), toDefs(pipes, extractPipeDef));
|
||||
return toHtml(containerEl);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,10 +10,10 @@ import {InitialStylingFlags, RenderFlags} from '../../../src/render3/interfaces/
|
|||
import {LElementNode} from '../../../src/render3/interfaces/node';
|
||||
import {Renderer3} from '../../../src/render3/interfaces/renderer';
|
||||
import {StylingContext, StylingFlags, StylingIndex} from '../../../src/render3/interfaces/styling';
|
||||
import {allocStylingContext, createStylingContextTemplate, isContextDirty, renderStyling as _renderStyling, setContextDirty, updateClassProp, updateStyleProp, updateStylingMap} from '../../../src/render3/styling/class_and_style_bindings';
|
||||
import {createStylingContextTemplate, isContextDirty, renderStyling as _renderStyling, setContextDirty, updateClassProp, updateStyleProp, updateStylingMap} from '../../../src/render3/styling/class_and_style_bindings';
|
||||
import {allocStylingContext} from '../../../src/render3/styling/util';
|
||||
import {defaultStyleSanitizer} from '../../../src/sanitization/sanitization';
|
||||
import {StyleSanitizeFn} from '../../../src/sanitization/style_sanitizer';
|
||||
|
||||
import {renderToHtml} from '../render_util';
|
||||
|
||||
describe('styling', () => {
|
||||
|
@ -110,19 +110,19 @@ describe('styling', () => {
|
|||
describe('createStylingContextTemplate', () => {
|
||||
it('should initialize empty template', () => {
|
||||
const template = initContext();
|
||||
expect(template).toEqual([element, null, null, [null], cleanStyle(0, 8), 0, null, null]);
|
||||
expect(template).toEqual([null, null, [null], cleanStyle(0, 8), 0, element, null, null]);
|
||||
});
|
||||
|
||||
it('should initialize static styles', () => {
|
||||
const template =
|
||||
initContext([InitialStylingFlags.VALUES_MODE, 'color', 'red', 'width', '10px']);
|
||||
expect(template).toEqual([
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
[null, 'red', '10px'],
|
||||
dirtyStyle(0, 14), //
|
||||
0,
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
|
||||
|
@ -321,12 +321,12 @@ describe('styling', () => {
|
|||
updateStyles(stylingContext, {width: '100px', height: '100px'});
|
||||
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
[null],
|
||||
dirtyStyle(0, 14), //
|
||||
2,
|
||||
element,
|
||||
null,
|
||||
{width: '100px', height: '100px'},
|
||||
|
||||
|
@ -355,12 +355,12 @@ describe('styling', () => {
|
|||
updateStyles(stylingContext, {width: '200px', opacity: '0'});
|
||||
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
[null],
|
||||
dirtyStyle(0, 14), //
|
||||
2,
|
||||
element,
|
||||
null,
|
||||
{width: '200px', opacity: '0'},
|
||||
|
||||
|
@ -392,12 +392,12 @@ describe('styling', () => {
|
|||
|
||||
getStyles(stylingContext);
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
[null],
|
||||
cleanStyle(0, 14), //
|
||||
2,
|
||||
element,
|
||||
null,
|
||||
{width: '200px', opacity: '0'},
|
||||
|
||||
|
@ -431,12 +431,12 @@ describe('styling', () => {
|
|||
updateStyleProp(stylingContext, 0, '300px');
|
||||
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
[null],
|
||||
dirtyStyle(0, 14), //
|
||||
2,
|
||||
element,
|
||||
null,
|
||||
{width: null},
|
||||
|
||||
|
@ -470,12 +470,12 @@ describe('styling', () => {
|
|||
|
||||
updateStyleProp(stylingContext, 0, null);
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
[null],
|
||||
dirtyStyle(0, 14), //
|
||||
2,
|
||||
element,
|
||||
null,
|
||||
{width: null},
|
||||
|
||||
|
@ -514,12 +514,12 @@ describe('styling', () => {
|
|||
updateStyles(stylingContext, {width: '100px', height: '100px', opacity: '0.5'});
|
||||
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
[null],
|
||||
dirtyStyle(0, 11), //
|
||||
1,
|
||||
element,
|
||||
null,
|
||||
{width: '100px', height: '100px', opacity: '0.5'},
|
||||
|
||||
|
@ -553,12 +553,12 @@ describe('styling', () => {
|
|||
|
||||
updateStyles(stylingContext, {});
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
[null],
|
||||
dirtyStyle(0, 11), //
|
||||
1,
|
||||
element,
|
||||
null,
|
||||
{},
|
||||
|
||||
|
@ -594,12 +594,12 @@ describe('styling', () => {
|
|||
});
|
||||
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
[null],
|
||||
dirtyStyle(0, 11), //
|
||||
1,
|
||||
element,
|
||||
null,
|
||||
{borderWidth: '5px'},
|
||||
|
||||
|
@ -637,12 +637,12 @@ describe('styling', () => {
|
|||
updateStyleProp(stylingContext, 0, '200px');
|
||||
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
[null],
|
||||
dirtyStyle(0, 11), //
|
||||
1,
|
||||
element,
|
||||
null,
|
||||
{borderWidth: '5px'},
|
||||
|
||||
|
@ -680,12 +680,12 @@ describe('styling', () => {
|
|||
updateStyles(stylingContext, {borderWidth: '15px', borderColor: 'red'});
|
||||
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
[null],
|
||||
dirtyStyle(0, 11), //
|
||||
1,
|
||||
element,
|
||||
null,
|
||||
{borderWidth: '15px', borderColor: 'red'},
|
||||
|
||||
|
@ -737,12 +737,12 @@ describe('styling', () => {
|
|||
updateStyleProp(stylingContext, 0, '200px');
|
||||
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
[null],
|
||||
dirtyStyle(0, 11), //
|
||||
1,
|
||||
element,
|
||||
null,
|
||||
{width: '100px'},
|
||||
|
||||
|
@ -765,12 +765,12 @@ describe('styling', () => {
|
|||
getStyles(stylingContext);
|
||||
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
[null],
|
||||
cleanStyle(0, 11), //
|
||||
1,
|
||||
element,
|
||||
null,
|
||||
{width: '100px'},
|
||||
|
||||
|
@ -802,12 +802,12 @@ describe('styling', () => {
|
|||
updateStyleProp(stylingContext, 1, '100px');
|
||||
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
styleSanitizer,
|
||||
[null],
|
||||
dirtyStyle(0, 14), //
|
||||
2,
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
|
||||
|
@ -835,12 +835,12 @@ describe('styling', () => {
|
|||
updateStyles(stylingContext, {'background-image': 'unsafe'});
|
||||
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
styleSanitizer,
|
||||
[null],
|
||||
dirtyStyle(0, 14), //
|
||||
2,
|
||||
element,
|
||||
null,
|
||||
{'background-image': 'unsafe'},
|
||||
|
||||
|
@ -873,12 +873,12 @@ describe('styling', () => {
|
|||
getStyles(stylingContext);
|
||||
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
styleSanitizer,
|
||||
[null],
|
||||
cleanStyle(0, 14), //
|
||||
2,
|
||||
element,
|
||||
null,
|
||||
{'background-image': 'unsafe'},
|
||||
|
||||
|
@ -916,8 +916,8 @@ describe('styling', () => {
|
|||
const template =
|
||||
initContext(null, [InitialStylingFlags.VALUES_MODE, 'one', true, 'two', true]);
|
||||
expect(template).toEqual([
|
||||
element, null, null, [null, true, true], dirtyStyle(0, 14), //
|
||||
0, null, null,
|
||||
null, null, [null, true, true], dirtyStyle(0, 14), //
|
||||
0, element, null, null,
|
||||
|
||||
// #8
|
||||
cleanClass(1, 14), 'one', null,
|
||||
|
@ -979,12 +979,12 @@ describe('styling', () => {
|
|||
const initialClasses = ['wide', 'tall', InitialStylingFlags.VALUES_MODE, 'wide', true];
|
||||
const stylingContext = initContext(initialStyles, initialClasses);
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
[null, '100px', true],
|
||||
dirtyStyle(0, 20), //
|
||||
2,
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
|
||||
|
@ -1033,12 +1033,12 @@ describe('styling', () => {
|
|||
|
||||
updateStylingMap(stylingContext, 'tall round', {width: '200px', opacity: '0.5'});
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
[null, '100px', true],
|
||||
dirtyStyle(0, 20), //
|
||||
2,
|
||||
element,
|
||||
'tall round',
|
||||
{width: '200px', opacity: '0.5'},
|
||||
|
||||
|
@ -1101,12 +1101,12 @@ describe('styling', () => {
|
|||
updateStyleProp(stylingContext, 0, '300px');
|
||||
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
[null, '100px', true],
|
||||
dirtyStyle(0, 20), //
|
||||
2,
|
||||
element,
|
||||
{tall: true, wide: true},
|
||||
{width: '500px'},
|
||||
|
||||
|
@ -1179,12 +1179,12 @@ describe('styling', () => {
|
|||
getStylesAndClasses(stylingContext);
|
||||
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
[null],
|
||||
cleanStyle(0, 8), //
|
||||
0,
|
||||
element,
|
||||
{foo: true},
|
||||
{width: '200px'},
|
||||
|
||||
|
@ -1208,12 +1208,12 @@ describe('styling', () => {
|
|||
getStylesAndClasses(stylingContext);
|
||||
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
[null],
|
||||
cleanStyle(0, 8), //
|
||||
0,
|
||||
element,
|
||||
{foo: false},
|
||||
{width: '300px'},
|
||||
|
||||
|
@ -1240,12 +1240,12 @@ describe('styling', () => {
|
|||
expect(getClasses(stylingContext)).toEqual({apple: true, orange: true, banana: true});
|
||||
|
||||
expect(stylingContext).toEqual([
|
||||
element,
|
||||
null,
|
||||
null,
|
||||
[null],
|
||||
cleanStyle(0, 8), //
|
||||
0,
|
||||
element,
|
||||
'apple orange banana',
|
||||
null,
|
||||
|
||||
|
|
Loading…
Reference in New Issue