refactor(ivy): Intruduce LFrame to store global instruction information (#33178)
`LFrame` stores information specifice to the current `LView` As the code enters and leaves `LView`s we use `enterView()` and `leaveView()` respectively to build a a stack of `LFrame`s. This allows us to easily restore the previous `LView` instruction state. PR Close #33178
This commit is contained in:
parent
9ea3430a5b
commit
09a2bb839f
@ -12,7 +12,7 @@
|
|||||||
"master": {
|
"master": {
|
||||||
"uncompressed": {
|
"uncompressed": {
|
||||||
"runtime-es2015": 1485,
|
"runtime-es2015": 1485,
|
||||||
"main-es2015": 14440,
|
"main-es2015": 14678,
|
||||||
"polyfills-es2015": 36808
|
"polyfills-es2015": 36808
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,4 +64,4 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -23,7 +23,7 @@ import {TElementNode, TNode, TNodeType} from './interfaces/node';
|
|||||||
import {PlayerHandler} from './interfaces/player';
|
import {PlayerHandler} from './interfaces/player';
|
||||||
import {RElement, Renderer3, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
|
import {RElement, Renderer3, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
|
||||||
import {CONTEXT, HEADER_OFFSET, LView, LViewFlags, RootContext, RootContextFlags, TVIEW} from './interfaces/view';
|
import {CONTEXT, HEADER_OFFSET, LView, LViewFlags, RootContext, RootContextFlags, TVIEW} from './interfaces/view';
|
||||||
import {getPreviousOrParentTNode, incrementActiveDirectiveId, resetComponentState, selectView, setActiveHostElement} from './state';
|
import {enterView, getPreviousOrParentTNode, incrementActiveDirectiveId, leaveView, setActiveHostElement} from './state';
|
||||||
import {publishDefaultGlobalUtils} from './util/global_utils';
|
import {publishDefaultGlobalUtils} from './util/global_utils';
|
||||||
import {defaultScheduler, stringifyForError} from './util/misc_utils';
|
import {defaultScheduler, stringifyForError} from './util/misc_utils';
|
||||||
import {getRootContext} from './util/view_traversal_utils';
|
import {getRootContext} from './util/view_traversal_utils';
|
||||||
@ -111,10 +111,6 @@ export function renderComponent<T>(
|
|||||||
ngDevMode && publishDefaultGlobalUtils();
|
ngDevMode && publishDefaultGlobalUtils();
|
||||||
ngDevMode && assertComponentType(componentType);
|
ngDevMode && assertComponentType(componentType);
|
||||||
|
|
||||||
// this is preemptively set to avoid having test and debug code accidentally
|
|
||||||
// read data from a previous application state...
|
|
||||||
setActiveHostElement(null);
|
|
||||||
|
|
||||||
const rendererFactory = opts.rendererFactory || domRendererFactory3;
|
const rendererFactory = opts.rendererFactory || domRendererFactory3;
|
||||||
const sanitizer = opts.sanitizer || null;
|
const sanitizer = opts.sanitizer || null;
|
||||||
const componentDef = getComponentDef<T>(componentType) !;
|
const componentDef = getComponentDef<T>(componentType) !;
|
||||||
@ -133,7 +129,7 @@ export function renderComponent<T>(
|
|||||||
null, rootTView, rootContext, rootFlags, null, null, rendererFactory, renderer, undefined,
|
null, rootTView, rootContext, rootFlags, null, null, rendererFactory, renderer, undefined,
|
||||||
opts.injector || null);
|
opts.injector || null);
|
||||||
|
|
||||||
const oldView = selectView(rootView, null);
|
enterView(rootView, null);
|
||||||
let component: T;
|
let component: T;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -149,7 +145,7 @@ export function renderComponent<T>(
|
|||||||
refreshView(rootView, rootTView, null, null);
|
refreshView(rootView, rootTView, null, null);
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
selectView(oldView, null);
|
leaveView();
|
||||||
if (rendererFactory.end) rendererFactory.end();
|
if (rendererFactory.end) rendererFactory.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +166,6 @@ export function renderComponent<T>(
|
|||||||
export function createRootComponentView(
|
export function createRootComponentView(
|
||||||
rNode: RElement | null, def: ComponentDef<any>, rootView: LView,
|
rNode: RElement | null, def: ComponentDef<any>, rootView: LView,
|
||||||
rendererFactory: RendererFactory3, renderer: Renderer3, sanitizer?: Sanitizer | null): LView {
|
rendererFactory: RendererFactory3, renderer: Renderer3, sanitizer?: Sanitizer | null): LView {
|
||||||
resetComponentState();
|
|
||||||
const tView = rootView[TVIEW];
|
const tView = rootView[TVIEW];
|
||||||
ngDevMode && assertDataInRange(rootView, 0 + HEADER_OFFSET);
|
ngDevMode && assertDataInRange(rootView, 0 + HEADER_OFFSET);
|
||||||
rootView[0 + HEADER_OFFSET] = rNode;
|
rootView[0 + HEADER_OFFSET] = rNode;
|
||||||
|
@ -29,7 +29,7 @@ import {ComponentDef} from './interfaces/definition';
|
|||||||
import {TContainerNode, TElementContainerNode, TElementNode} from './interfaces/node';
|
import {TContainerNode, TElementContainerNode, TElementNode} from './interfaces/node';
|
||||||
import {RNode, RendererFactory3, domRendererFactory3, isProceduralRenderer} from './interfaces/renderer';
|
import {RNode, RendererFactory3, domRendererFactory3, isProceduralRenderer} from './interfaces/renderer';
|
||||||
import {LView, LViewFlags, TVIEW} from './interfaces/view';
|
import {LView, LViewFlags, TVIEW} from './interfaces/view';
|
||||||
import {namespaceHTMLInternal, selectView} from './state';
|
import {enterView, leaveView} from './state';
|
||||||
import {defaultScheduler} from './util/misc_utils';
|
import {defaultScheduler} from './util/misc_utils';
|
||||||
import {getTNode} from './util/view_utils';
|
import {getTNode} from './util/view_utils';
|
||||||
import {createElementRef} from './view_engine_compatibility';
|
import {createElementRef} from './view_engine_compatibility';
|
||||||
@ -133,9 +133,6 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
|
|||||||
rootViewInjector.get(RendererFactory2, domRendererFactory3) as RendererFactory3;
|
rootViewInjector.get(RendererFactory2, domRendererFactory3) as RendererFactory3;
|
||||||
const sanitizer = rootViewInjector.get(Sanitizer, null);
|
const sanitizer = rootViewInjector.get(Sanitizer, null);
|
||||||
|
|
||||||
// Ensure that the namespace for the root node is correct,
|
|
||||||
// otherwise the browser might not render out the element properly.
|
|
||||||
namespaceHTMLInternal();
|
|
||||||
const hostRNode = rootSelectorOrNode ?
|
const hostRNode = rootSelectorOrNode ?
|
||||||
locateHostElement(rendererFactory, rootSelectorOrNode) :
|
locateHostElement(rendererFactory, rootSelectorOrNode) :
|
||||||
elementCreate(this.selector, rendererFactory.createRenderer(null, this.componentDef), null);
|
elementCreate(this.selector, rendererFactory.createRenderer(null, this.componentDef), null);
|
||||||
@ -167,7 +164,11 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
|
|||||||
rootViewInjector);
|
rootViewInjector);
|
||||||
|
|
||||||
// rootView is the parent when bootstrapping
|
// rootView is the parent when bootstrapping
|
||||||
const oldLView = selectView(rootLView, null);
|
// TODO(misko): it looks like we are entering view here but we don't really need to as
|
||||||
|
// `renderView` does that. However as the code is written it is needed because
|
||||||
|
// `createRootComponentView` and `createRootComponent` both read global state. Fixing those
|
||||||
|
// issues would allow us to drop this.
|
||||||
|
enterView(rootLView, null);
|
||||||
|
|
||||||
let component: T;
|
let component: T;
|
||||||
let tElementNode: TElementNode;
|
let tElementNode: TElementNode;
|
||||||
@ -194,7 +195,7 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
|
|||||||
|
|
||||||
renderView(rootLView, rootTView, null);
|
renderView(rootLView, rootTView, null);
|
||||||
} finally {
|
} finally {
|
||||||
selectView(oldLView, null);
|
leaveView();
|
||||||
}
|
}
|
||||||
|
|
||||||
const componentRef = new ComponentRef(
|
const componentRef = new ComponentRef(
|
||||||
|
@ -10,7 +10,7 @@ import {isForwardRef, resolveForwardRef} from '../di/forward_ref';
|
|||||||
import {InjectionToken} from '../di/injection_token';
|
import {InjectionToken} from '../di/injection_token';
|
||||||
import {Injector} from '../di/injector';
|
import {Injector} from '../di/injector';
|
||||||
import {injectRootLimpMode, setInjectImplementation} from '../di/injector_compatibility';
|
import {injectRootLimpMode, setInjectImplementation} from '../di/injector_compatibility';
|
||||||
import {getInjectableDef, getInjectorDef} from '../di/interface/defs';
|
import {getInjectorDef} from '../di/interface/defs';
|
||||||
import {InjectFlags} from '../di/interface/injector';
|
import {InjectFlags} from '../di/interface/injector';
|
||||||
import {Type} from '../interface/type';
|
import {Type} from '../interface/type';
|
||||||
import {assertDefined, assertEqual} from '../util/assert';
|
import {assertDefined, assertEqual} from '../util/assert';
|
||||||
@ -19,11 +19,11 @@ import {getFactoryDef} from './definition';
|
|||||||
import {NG_ELEMENT_ID, NG_FACTORY_DEF} from './fields';
|
import {NG_ELEMENT_ID, NG_FACTORY_DEF} from './fields';
|
||||||
import {DirectiveDef, FactoryFn} from './interfaces/definition';
|
import {DirectiveDef, FactoryFn} from './interfaces/definition';
|
||||||
import {NO_PARENT_INJECTOR, NodeInjectorFactory, PARENT_INJECTOR, RelativeInjectorLocation, RelativeInjectorLocationFlags, TNODE, isFactory} from './interfaces/injector';
|
import {NO_PARENT_INJECTOR, NodeInjectorFactory, PARENT_INJECTOR, RelativeInjectorLocation, RelativeInjectorLocationFlags, TNODE, isFactory} from './interfaces/injector';
|
||||||
import {AttributeMarker, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeProviderIndexes, TNodeType} from './interfaces/node';
|
import {AttributeMarker, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeProviderIndexes, TNodeType} from './interfaces/node';
|
||||||
import {isComponentDef, isComponentHost} from './interfaces/type_checks';
|
import {isComponentDef, isComponentHost} from './interfaces/type_checks';
|
||||||
import {DECLARATION_VIEW, INJECTOR, LView, TData, TVIEW, TView, T_HOST} from './interfaces/view';
|
import {DECLARATION_VIEW, INJECTOR, LView, TData, TVIEW, TView, T_HOST} from './interfaces/view';
|
||||||
import {assertNodeOfPossibleTypes} from './node_assert';
|
import {assertNodeOfPossibleTypes} from './node_assert';
|
||||||
import {getLView, getPreviousOrParentTNode, setTNodeAndViewData} from './state';
|
import {enterDI, leaveDI} from './state';
|
||||||
import {isNameOnlyAttributeMarker} from './util/attrs_utils';
|
import {isNameOnlyAttributeMarker} from './util/attrs_utils';
|
||||||
import {getParentInjectorIndex, getParentInjectorView, hasParentInjector} from './util/injector_utils';
|
import {getParentInjectorIndex, getParentInjectorView, hasParentInjector} from './util/injector_utils';
|
||||||
import {stringifyForError} from './util/misc_utils';
|
import {stringifyForError} from './util/misc_utils';
|
||||||
@ -334,9 +334,7 @@ export function getOrCreateInjectable<T>(
|
|||||||
// If the ID stored here is a function, this is a special object like ElementRef or TemplateRef
|
// If the ID stored here is a function, this is a special object like ElementRef or TemplateRef
|
||||||
// so just call the factory function to create it.
|
// so just call the factory function to create it.
|
||||||
if (typeof bloomHash === 'function') {
|
if (typeof bloomHash === 'function') {
|
||||||
const savePreviousOrParentTNode = getPreviousOrParentTNode();
|
enterDI(lView, tNode);
|
||||||
const saveLView = getLView();
|
|
||||||
setTNodeAndViewData(tNode, lView);
|
|
||||||
try {
|
try {
|
||||||
const value = bloomHash();
|
const value = bloomHash();
|
||||||
if (value == null && !(flags & InjectFlags.Optional)) {
|
if (value == null && !(flags & InjectFlags.Optional)) {
|
||||||
@ -345,7 +343,7 @@ export function getOrCreateInjectable<T>(
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
setTNodeAndViewData(savePreviousOrParentTNode, saveLView);
|
leaveDI();
|
||||||
}
|
}
|
||||||
} else if (typeof bloomHash == 'number') {
|
} else if (typeof bloomHash == 'number') {
|
||||||
if (bloomHash === -1) {
|
if (bloomHash === -1) {
|
||||||
@ -530,8 +528,8 @@ export function locateDirectiveOrProvider<T>(
|
|||||||
* instantiates the `injectable` and caches the value.
|
* instantiates the `injectable` and caches the value.
|
||||||
*/
|
*/
|
||||||
export function getNodeInjectable(
|
export function getNodeInjectable(
|
||||||
tData: TData, lData: LView, index: number, tNode: TElementNode): any {
|
tData: TData, lView: LView, index: number, tNode: TElementNode): any {
|
||||||
let value = lData[index];
|
let value = lView[index];
|
||||||
if (isFactory(value)) {
|
if (isFactory(value)) {
|
||||||
const factory: NodeInjectorFactory = value;
|
const factory: NodeInjectorFactory = value;
|
||||||
if (factory.resolving) {
|
if (factory.resolving) {
|
||||||
@ -543,16 +541,14 @@ export function getNodeInjectable(
|
|||||||
if (factory.injectImpl) {
|
if (factory.injectImpl) {
|
||||||
previousInjectImplementation = setInjectImplementation(factory.injectImpl);
|
previousInjectImplementation = setInjectImplementation(factory.injectImpl);
|
||||||
}
|
}
|
||||||
const savePreviousOrParentTNode = getPreviousOrParentTNode();
|
enterDI(lView, tNode);
|
||||||
const saveLView = getLView();
|
|
||||||
setTNodeAndViewData(tNode, lData);
|
|
||||||
try {
|
try {
|
||||||
value = lData[index] = factory.factory(undefined, tData, lData, tNode);
|
value = lView[index] = factory.factory(undefined, tData, lView, tNode);
|
||||||
} finally {
|
} finally {
|
||||||
if (factory.injectImpl) setInjectImplementation(previousInjectImplementation);
|
if (factory.injectImpl) setInjectImplementation(previousInjectImplementation);
|
||||||
setIncludeViewProviders(previousIncludeViewProviders);
|
setIncludeViewProviders(previousIncludeViewProviders);
|
||||||
factory.resolving = false;
|
factory.resolving = false;
|
||||||
setTNodeAndViewData(savePreviousOrParentTNode, saveLView);
|
leaveDI();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
|
@ -14,12 +14,12 @@ import {TContainerNode, TNodeType} from '../interfaces/node';
|
|||||||
import {CONTEXT, LView, LViewFlags, PARENT, TVIEW, TView, T_HOST} from '../interfaces/view';
|
import {CONTEXT, LView, LViewFlags, PARENT, TVIEW, TView, T_HOST} from '../interfaces/view';
|
||||||
import {assertNodeType} from '../node_assert';
|
import {assertNodeType} from '../node_assert';
|
||||||
import {insertView, removeView} from '../node_manipulation';
|
import {insertView, removeView} from '../node_manipulation';
|
||||||
import {getIsParent, getLView, getPreviousOrParentTNode, selectView, setIsParent, setPreviousOrParentTNode} from '../state';
|
import {enterView, getIsParent, getLView, getPreviousOrParentTNode, leaveViewProcessExit, setIsParent, setPreviousOrParentTNode} from '../state';
|
||||||
import {isCreationMode} from '../util/view_utils';
|
import {isCreationMode} from '../util/view_utils';
|
||||||
|
|
||||||
import {assignTViewNodeToLView, createLView, createTView, refreshView, renderView} from './shared';
|
import {assignTViewNodeToLView, createLView, createTView, refreshView, renderView} from './shared';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the start of an embedded view.
|
* Marks the start of an embedded view.
|
||||||
*
|
*
|
||||||
@ -42,7 +42,7 @@ export function ɵɵembeddedViewStart(viewBlockId: number, decls: number, vars:
|
|||||||
|
|
||||||
if (viewToRender) {
|
if (viewToRender) {
|
||||||
setIsParent();
|
setIsParent();
|
||||||
selectView(viewToRender, viewToRender[TVIEW].node);
|
enterView(viewToRender, viewToRender[TVIEW].node);
|
||||||
} else {
|
} else {
|
||||||
// When we create a new LView, we always reset the state of the instructions.
|
// When we create a new LView, we always reset the state of the instructions.
|
||||||
viewToRender = createLView(
|
viewToRender = createLView(
|
||||||
@ -52,7 +52,7 @@ export function ɵɵembeddedViewStart(viewBlockId: number, decls: number, vars:
|
|||||||
const tParentNode = getIsParent() ? previousOrParentTNode :
|
const tParentNode = getIsParent() ? previousOrParentTNode :
|
||||||
previousOrParentTNode && previousOrParentTNode.parent;
|
previousOrParentTNode && previousOrParentTNode.parent;
|
||||||
assignTViewNodeToLView(viewToRender[TVIEW], tParentNode, viewBlockId, viewToRender);
|
assignTViewNodeToLView(viewToRender[TVIEW], tParentNode, viewBlockId, viewToRender);
|
||||||
selectView(viewToRender, viewToRender[TVIEW].node);
|
enterView(viewToRender, viewToRender[TVIEW].node);
|
||||||
}
|
}
|
||||||
if (lContainer) {
|
if (lContainer) {
|
||||||
if (isCreationMode(viewToRender)) {
|
if (isCreationMode(viewToRender)) {
|
||||||
@ -138,6 +138,6 @@ export function ɵɵembeddedViewEnd(): void {
|
|||||||
|
|
||||||
const lContainer = lView[PARENT] as LContainer;
|
const lContainer = lView[PARENT] as LContainer;
|
||||||
ngDevMode && assertLContainerOrUndefined(lContainer);
|
ngDevMode && assertLContainerOrUndefined(lContainer);
|
||||||
selectView(lContainer[PARENT] !, null);
|
leaveViewProcessExit();
|
||||||
setPreviousOrParentTNode(viewHost !, false);
|
setPreviousOrParentTNode(viewHost !, false);
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,11 @@ import {CLEANUP, FLAGS, LView, LViewFlags, RENDERER, TVIEW} from '../interfaces/
|
|||||||
import {assertNodeOfPossibleTypes} from '../node_assert';
|
import {assertNodeOfPossibleTypes} from '../node_assert';
|
||||||
import {getLView, getPreviousOrParentTNode} from '../state';
|
import {getLView, getPreviousOrParentTNode} from '../state';
|
||||||
import {getComponentLViewByIndex, getNativeByTNode, unwrapRNode} from '../util/view_utils';
|
import {getComponentLViewByIndex, getNativeByTNode, unwrapRNode} from '../util/view_utils';
|
||||||
|
|
||||||
import {getCleanup, handleError, loadComponentRenderer, markViewDirty} from './shared';
|
import {getCleanup, handleError, loadComponentRenderer, markViewDirty} from './shared';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an event listener to the current node.
|
* Adds an event listener to the current node.
|
||||||
*
|
*
|
||||||
@ -213,7 +216,7 @@ function listenerInternal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function executeListenerWithErrorHandling(
|
function executeListenerWithErrorHandling(
|
||||||
lView: LView, listenerFn: (e?: any) => any, e: any): boolean {
|
lView: LView, tNode: TNode, listenerFn: (e?: any) => any, e: any): boolean {
|
||||||
try {
|
try {
|
||||||
// Only explicitly returning false from a listener should preventDefault
|
// Only explicitly returning false from a listener should preventDefault
|
||||||
return listenerFn(e) !== false;
|
return listenerFn(e) !== false;
|
||||||
@ -256,13 +259,13 @@ function wrapListener(
|
|||||||
markViewDirty(startView);
|
markViewDirty(startView);
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = executeListenerWithErrorHandling(lView, listenerFn, e);
|
let result = executeListenerWithErrorHandling(lView, tNode, listenerFn, e);
|
||||||
// A just-invoked listener function might have coalesced listeners so we need to check for
|
// A just-invoked listener function might have coalesced listeners so we need to check for
|
||||||
// their presence and invoke as needed.
|
// their presence and invoke as needed.
|
||||||
let nextListenerFn = (<any>wrapListenerIn_markDirtyAndPreventDefault).__ngNextListenerFn__;
|
let nextListenerFn = (<any>wrapListenerIn_markDirtyAndPreventDefault).__ngNextListenerFn__;
|
||||||
while (nextListenerFn) {
|
while (nextListenerFn) {
|
||||||
// We should prevent default if any of the listeners explicitly return false
|
// We should prevent default if any of the listeners explicitly return false
|
||||||
result = executeListenerWithErrorHandling(lView, nextListenerFn, e) && result;
|
result = executeListenerWithErrorHandling(lView, tNode, nextListenerFn, e) && result;
|
||||||
nextListenerFn = (<any>nextListenerFn).__ngNextListenerFn__;
|
nextListenerFn = (<any>nextListenerFn).__ngNextListenerFn__;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ import {createNamedArrayType} from '../../util/named_array_type';
|
|||||||
import {initNgDevMode} from '../../util/ng_dev_mode';
|
import {initNgDevMode} from '../../util/ng_dev_mode';
|
||||||
import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../../util/ng_reflect';
|
import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../../util/ng_reflect';
|
||||||
import {assertFirstTemplatePass, assertLView} from '../assert';
|
import {assertFirstTemplatePass, assertLView} from '../assert';
|
||||||
import {attachPatchData, getComponentViewByInstance} from '../context_discovery';
|
import {attachPatchData} from '../context_discovery';
|
||||||
import {getFactoryDef} from '../definition';
|
import {getFactoryDef} from '../definition';
|
||||||
import {diPublicInInjector, getNodeInjectable, getOrCreateNodeInjectorForNode} from '../di';
|
import {diPublicInInjector, getNodeInjectable, getOrCreateNodeInjectorForNode} from '../di';
|
||||||
import {throwMultipleComponentError} from '../errors';
|
import {throwMultipleComponentError} from '../errors';
|
||||||
@ -30,7 +30,7 @@ import {isComponentDef, isComponentHost, isContentQueryHost, isLContainer, isRoo
|
|||||||
import {BINDING_INDEX, CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DECLARATION_VIEW, ExpandoInstructions, FLAGS, HEADER_OFFSET, HOST, INJECTOR, InitPhaseState, LView, LViewFlags, NEXT, PARENT, RENDERER, RENDERER_FACTORY, RootContext, RootContextFlags, SANITIZER, TData, TVIEW, TView, T_HOST} from '../interfaces/view';
|
import {BINDING_INDEX, CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DECLARATION_VIEW, ExpandoInstructions, FLAGS, HEADER_OFFSET, HOST, INJECTOR, InitPhaseState, LView, LViewFlags, NEXT, PARENT, RENDERER, RENDERER_FACTORY, RootContext, RootContextFlags, SANITIZER, TData, TVIEW, TView, T_HOST} from '../interfaces/view';
|
||||||
import {assertNodeOfPossibleTypes} from '../node_assert';
|
import {assertNodeOfPossibleTypes} from '../node_assert';
|
||||||
import {isNodeMatchingSelectorList} from '../node_selector_matcher';
|
import {isNodeMatchingSelectorList} from '../node_selector_matcher';
|
||||||
import {ActiveElementFlags, executeElementExitFn, getBindingsEnabled, getCheckNoChangesMode, getIsParent, getPreviousOrParentTNode, getSelectedIndex, hasActiveElementFlag, incrementActiveDirectiveId, namespaceHTMLInternal, selectView, setActiveHostElement, setBindingRoot, setCheckNoChangesMode, setCurrentDirectiveDef, setCurrentQueryIndex, setPreviousOrParentTNode, setSelectedIndex} from '../state';
|
import {ActiveElementFlags, enterView, executeElementExitFn, getBindingsEnabled, getCheckNoChangesMode, getIsParent, getPreviousOrParentTNode, getSelectedIndex, hasActiveElementFlag, incrementActiveDirectiveId, leaveView, leaveViewProcessExit, setActiveHostElement, setBindingRoot, setCheckNoChangesMode, setCurrentDirectiveDef, setCurrentQueryIndex, setPreviousOrParentTNode, setSelectedIndex} from '../state';
|
||||||
import {renderStylingMap} from '../styling/bindings';
|
import {renderStylingMap} from '../styling/bindings';
|
||||||
import {NO_CHANGE} from '../tokens';
|
import {NO_CHANGE} from '../tokens';
|
||||||
import {isAnimationProp} from '../util/attrs_utils';
|
import {isAnimationProp} from '../util/attrs_utils';
|
||||||
@ -312,7 +312,7 @@ export function allocExpando(view: LView, numSlotsToAlloc: number) {
|
|||||||
*/
|
*/
|
||||||
export function renderView<T>(lView: LView, tView: TView, context: T): void {
|
export function renderView<T>(lView: LView, tView: TView, context: T): void {
|
||||||
ngDevMode && assertEqual(isCreationMode(lView), true, 'Should be run in creation mode');
|
ngDevMode && assertEqual(isCreationMode(lView), true, 'Should be run in creation mode');
|
||||||
const oldView = selectView(lView, lView[T_HOST]);
|
enterView(lView, lView[T_HOST]);
|
||||||
try {
|
try {
|
||||||
const viewQuery = tView.viewQuery;
|
const viewQuery = tView.viewQuery;
|
||||||
if (viewQuery !== null) {
|
if (viewQuery !== null) {
|
||||||
@ -357,7 +357,7 @@ export function renderView<T>(lView: LView, tView: TView, context: T): void {
|
|||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
lView[FLAGS] &= ~LViewFlags.CreationMode;
|
lView[FLAGS] &= ~LViewFlags.CreationMode;
|
||||||
selectView(oldView, null);
|
leaveView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,7 +372,7 @@ export function renderView<T>(lView: LView, tView: TView, context: T): void {
|
|||||||
export function refreshView<T>(
|
export function refreshView<T>(
|
||||||
lView: LView, tView: TView, templateFn: ComponentTemplate<{}>| null, context: T) {
|
lView: LView, tView: TView, templateFn: ComponentTemplate<{}>| null, context: T) {
|
||||||
ngDevMode && assertEqual(isCreationMode(lView), false, 'Should be run in update mode');
|
ngDevMode && assertEqual(isCreationMode(lView), false, 'Should be run in update mode');
|
||||||
const oldView = selectView(lView, lView[T_HOST]);
|
enterView(lView, lView[T_HOST]);
|
||||||
const flags = lView[FLAGS];
|
const flags = lView[FLAGS];
|
||||||
try {
|
try {
|
||||||
resetPreOrderHookFlags(lView);
|
resetPreOrderHookFlags(lView);
|
||||||
@ -463,7 +463,7 @@ export function refreshView<T>(
|
|||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
lView[FLAGS] &= ~(LViewFlags.Dirty | LViewFlags.FirstLViewPass);
|
lView[FLAGS] &= ~(LViewFlags.Dirty | LViewFlags.FirstLViewPass);
|
||||||
selectView(oldView, null);
|
leaveViewProcessExit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,8 +472,6 @@ export function renderComponentOrTemplate<T>(
|
|||||||
const rendererFactory = hostView[RENDERER_FACTORY];
|
const rendererFactory = hostView[RENDERER_FACTORY];
|
||||||
const normalExecutionPath = !getCheckNoChangesMode();
|
const normalExecutionPath = !getCheckNoChangesMode();
|
||||||
const creationModeIsActive = isCreationMode(hostView);
|
const creationModeIsActive = isCreationMode(hostView);
|
||||||
const previousOrParentTNode = getPreviousOrParentTNode();
|
|
||||||
const isParent = getIsParent();
|
|
||||||
try {
|
try {
|
||||||
if (normalExecutionPath && !creationModeIsActive && rendererFactory.begin) {
|
if (normalExecutionPath && !creationModeIsActive && rendererFactory.begin) {
|
||||||
rendererFactory.begin();
|
rendererFactory.begin();
|
||||||
@ -487,13 +485,11 @@ export function renderComponentOrTemplate<T>(
|
|||||||
if (normalExecutionPath && !creationModeIsActive && rendererFactory.end) {
|
if (normalExecutionPath && !creationModeIsActive && rendererFactory.end) {
|
||||||
rendererFactory.end();
|
rendererFactory.end();
|
||||||
}
|
}
|
||||||
setPreviousOrParentTNode(previousOrParentTNode, isParent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function executeTemplate<T>(
|
function executeTemplate<T>(
|
||||||
lView: LView, templateFn: ComponentTemplate<T>, rf: RenderFlags, context: T) {
|
lView: LView, templateFn: ComponentTemplate<T>, rf: RenderFlags, context: T) {
|
||||||
namespaceHTMLInternal();
|
|
||||||
const prevSelectedIndex = getSelectedIndex();
|
const prevSelectedIndex = getSelectedIndex();
|
||||||
try {
|
try {
|
||||||
setActiveHostElement(null);
|
setActiveHostElement(null);
|
||||||
@ -1659,9 +1655,6 @@ export function tickRootContext(rootContext: RootContext) {
|
|||||||
|
|
||||||
export function detectChangesInternal<T>(view: LView, context: T) {
|
export function detectChangesInternal<T>(view: LView, context: T) {
|
||||||
const rendererFactory = view[RENDERER_FACTORY];
|
const rendererFactory = view[RENDERER_FACTORY];
|
||||||
const previousOrParentTNode = getPreviousOrParentTNode();
|
|
||||||
const isParent = getIsParent();
|
|
||||||
|
|
||||||
if (rendererFactory.begin) rendererFactory.begin();
|
if (rendererFactory.begin) rendererFactory.begin();
|
||||||
try {
|
try {
|
||||||
const tView = view[TVIEW];
|
const tView = view[TVIEW];
|
||||||
@ -1671,7 +1664,6 @@ export function detectChangesInternal<T>(view: LView, context: T) {
|
|||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
if (rendererFactory.end) rendererFactory.end();
|
if (rendererFactory.end) rendererFactory.end();
|
||||||
setPreviousOrParentTNode(previousOrParentTNode, isParent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1684,18 +1676,6 @@ export function detectChangesInRootView(lView: LView): void {
|
|||||||
tickRootContext(lView[CONTEXT] as RootContext);
|
tickRootContext(lView[CONTEXT] as RootContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks the change detector and its children, and throws if any changes are detected.
|
|
||||||
*
|
|
||||||
* This is used in development mode to verify that running change detection doesn't
|
|
||||||
* introduce other changes.
|
|
||||||
*/
|
|
||||||
export function checkNoChanges<T>(component: T): void {
|
|
||||||
const view = getComponentViewByInstance(component);
|
|
||||||
checkNoChangesInternal<T>(view, component);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function checkNoChangesInternal<T>(view: LView, context: T) {
|
export function checkNoChangesInternal<T>(view: LView, context: T) {
|
||||||
setCheckNoChangesMode(true);
|
setCheckNoChangesMode(true);
|
||||||
try {
|
try {
|
||||||
|
@ -11,19 +11,28 @@ import {assertDefined, assertEqual} from '../util/assert';
|
|||||||
|
|
||||||
import {assertLViewOrUndefined} from './assert';
|
import {assertLViewOrUndefined} from './assert';
|
||||||
import {ComponentDef, DirectiveDef} from './interfaces/definition';
|
import {ComponentDef, DirectiveDef} from './interfaces/definition';
|
||||||
import {TElementNode, TNode, TViewNode} from './interfaces/node';
|
import {TNode} from './interfaces/node';
|
||||||
import {CONTEXT, DECLARATION_VIEW, LView, OpaqueViewState} from './interfaces/view';
|
import {BINDING_INDEX, CONTEXT, DECLARATION_VIEW, LView, OpaqueViewState, TVIEW} from './interfaces/view';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All implicit instruction state is stored here.
|
|
||||||
*
|
*
|
||||||
* It is useful to have a single object where all of the state is stored as a mental model
|
|
||||||
* (rather it being spread across many different variables.)
|
|
||||||
*
|
|
||||||
* PERF NOTE: Turns out that writing to a true global variable is slower than
|
|
||||||
* having an intermediate object with properties.
|
|
||||||
*/
|
*/
|
||||||
interface InstructionState {
|
interface LFrame {
|
||||||
|
/**
|
||||||
|
* Parent LFrame.
|
||||||
|
*
|
||||||
|
* This is needed when `leaveView` is called to restore the previous state.
|
||||||
|
*/
|
||||||
|
parent: LFrame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Child LFrame.
|
||||||
|
*
|
||||||
|
* This is used to cache existing LFrames to relieve the memory pressure.
|
||||||
|
*/
|
||||||
|
child: LFrame|null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* State of the current view being processed.
|
* State of the current view being processed.
|
||||||
*
|
*
|
||||||
@ -61,39 +70,14 @@ interface InstructionState {
|
|||||||
*/
|
*/
|
||||||
contextLView: LView;
|
contextLView: LView;
|
||||||
|
|
||||||
/**
|
|
||||||
* In this mode, any changes in bindings will throw an ExpressionChangedAfterChecked error.
|
|
||||||
*
|
|
||||||
* Necessary to support ChangeDetectorRef.checkNoChanges().
|
|
||||||
*/
|
|
||||||
checkNoChangesMode: boolean;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store the element depth count. This is used to identify the root elements of the template
|
* Store the element depth count. This is used to identify the root elements of the template
|
||||||
* so that we can then attach `LView` to only those elements.
|
* so that we can then attach patch data `LView` to only those elements. We know that those
|
||||||
|
* are the only places where the patch data could change, this way we will save on number
|
||||||
|
* of places where tha patching occurs.
|
||||||
*/
|
*/
|
||||||
elementDepthCount: number;
|
elementDepthCount: number;
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores whether directives should be matched to elements.
|
|
||||||
*
|
|
||||||
* When template contains `ngNonBindable` then we need to prevent the runtime form matching
|
|
||||||
* directives on children of that element.
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
* ```
|
|
||||||
* <my-comp my-directive>
|
|
||||||
* Should match component / directive.
|
|
||||||
* </my-comp>
|
|
||||||
* <div ngNonBindable>
|
|
||||||
* <my-comp my-directive>
|
|
||||||
* Should not match component / directive because we are in ngNonBindable.
|
|
||||||
* </my-comp>
|
|
||||||
* </div>
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
bindingsEnabled: boolean;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current namespace to be used when creating elements
|
* Current namespace to be used when creating elements
|
||||||
*/
|
*/
|
||||||
@ -131,7 +115,51 @@ interface InstructionState {
|
|||||||
* We iterate over the list of Queries and increment current query index at every step.
|
* We iterate over the list of Queries and increment current query index at every step.
|
||||||
*/
|
*/
|
||||||
currentQueryIndex: number;
|
currentQueryIndex: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All implicit instruction state is stored here.
|
||||||
|
*
|
||||||
|
* It is useful to have a single object where all of the state is stored as a mental model
|
||||||
|
* (rather it being spread across many different variables.)
|
||||||
|
*
|
||||||
|
* PERF NOTE: Turns out that writing to a true global variable is slower than
|
||||||
|
* having an intermediate object with properties.
|
||||||
|
*/
|
||||||
|
interface InstructionState {
|
||||||
|
/**
|
||||||
|
* Current `LFrame`
|
||||||
|
*
|
||||||
|
* `null` if we have not called `enterView`
|
||||||
|
*/
|
||||||
|
lFrame: LFrame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores whether directives should be matched to elements.
|
||||||
|
*
|
||||||
|
* When template contains `ngNonBindable` then we need to prevent the runtime from matching
|
||||||
|
* directives on children of that element.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```
|
||||||
|
* <my-comp my-directive>
|
||||||
|
* Should match component / directive.
|
||||||
|
* </my-comp>
|
||||||
|
* <div ngNonBindable>
|
||||||
|
* <my-comp my-directive>
|
||||||
|
* Should not match component / directive because we are in ngNonBindable.
|
||||||
|
* </my-comp>
|
||||||
|
* </div>
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
bindingsEnabled: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In this mode, any changes in bindings will throw an ExpressionChangedAfterChecked error.
|
||||||
|
*
|
||||||
|
* Necessary to support ChangeDetectorRef.checkNoChanges().
|
||||||
|
*/
|
||||||
|
checkNoChangesMode: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to be called when the element is exited.
|
* Function to be called when the element is exited.
|
||||||
@ -142,49 +170,34 @@ interface InstructionState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const instructionState: InstructionState = {
|
export const instructionState: InstructionState = {
|
||||||
previousOrParentTNode: null !,
|
lFrame: createLFrame(null),
|
||||||
isParent: null !,
|
|
||||||
lView: null !,
|
|
||||||
// tslint:disable-next-line: no-toplevel-property-access
|
|
||||||
selectedIndex: -1 << ActiveElementFlags.Size,
|
|
||||||
contextLView: null !,
|
|
||||||
checkNoChangesMode: false,
|
|
||||||
elementDepthCount: 0,
|
|
||||||
bindingsEnabled: true,
|
bindingsEnabled: true,
|
||||||
currentNamespace: null,
|
|
||||||
currentSanitizer: null,
|
|
||||||
currentDirectiveDef: null,
|
|
||||||
activeDirectiveId: 0,
|
|
||||||
bindingRootIndex: -1,
|
|
||||||
currentQueryIndex: 0,
|
|
||||||
elementExitFn: null,
|
elementExitFn: null,
|
||||||
|
checkNoChangesMode: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export function getElementDepthCount() {
|
export function getElementDepthCount() {
|
||||||
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
|
return instructionState.lFrame.elementDepthCount;
|
||||||
return instructionState.elementDepthCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function increaseElementDepthCount() {
|
export function increaseElementDepthCount() {
|
||||||
instructionState.elementDepthCount++;
|
instructionState.lFrame.elementDepthCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function decreaseElementDepthCount() {
|
export function decreaseElementDepthCount() {
|
||||||
instructionState.elementDepthCount--;
|
instructionState.lFrame.elementDepthCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCurrentDirectiveDef(): DirectiveDef<any>|ComponentDef<any>|null {
|
export function getCurrentDirectiveDef(): DirectiveDef<any>|ComponentDef<any>|null {
|
||||||
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
|
return instructionState.lFrame.currentDirectiveDef;
|
||||||
return instructionState.currentDirectiveDef;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setCurrentDirectiveDef(def: DirectiveDef<any>| ComponentDef<any>| null): void {
|
export function setCurrentDirectiveDef(def: DirectiveDef<any>| ComponentDef<any>| null): void {
|
||||||
instructionState.currentDirectiveDef = def;
|
instructionState.lFrame.currentDirectiveDef = def;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBindingsEnabled(): boolean {
|
export function getBindingsEnabled(): boolean {
|
||||||
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
|
|
||||||
return instructionState.bindingsEnabled;
|
return instructionState.bindingsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,8 +248,16 @@ export function ɵɵdisableBindings(): void {
|
|||||||
instructionState.bindingsEnabled = false;
|
instructionState.bindingsEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current LView.
|
||||||
|
*
|
||||||
|
* The return value can be `null` if the method is called outside of template. This can happen if
|
||||||
|
* directive is instantiated by module injector (rather than by node injector.)
|
||||||
|
*/
|
||||||
export function getLView(): LView {
|
export function getLView(): LView {
|
||||||
return instructionState.lView;
|
// TODO(misko): the return value should be `LView|null` but doing so breaks a lot of code.
|
||||||
|
const lFrame = instructionState.lFrame;
|
||||||
|
return lFrame === null ? null ! : lFrame.lView;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -259,14 +280,14 @@ export const enum ActiveElementFlags {
|
|||||||
* Determines whether or not a flag is currently set for the active element.
|
* Determines whether or not a flag is currently set for the active element.
|
||||||
*/
|
*/
|
||||||
export function hasActiveElementFlag(flag: ActiveElementFlags) {
|
export function hasActiveElementFlag(flag: ActiveElementFlags) {
|
||||||
return (instructionState.selectedIndex & flag) === flag;
|
return (instructionState.lFrame.selectedIndex & flag) === flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a flag is for the active element.
|
* Sets a flag is for the active element.
|
||||||
*/
|
*/
|
||||||
export function setActiveElementFlag(flag: ActiveElementFlags) {
|
function setActiveElementFlag(flag: ActiveElementFlags) {
|
||||||
instructionState.selectedIndex |= flag;
|
instructionState.lFrame.selectedIndex |= flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -277,20 +298,16 @@ export function setActiveElementFlag(flag: ActiveElementFlags) {
|
|||||||
* the directive/component instance lives
|
* the directive/component instance lives
|
||||||
*/
|
*/
|
||||||
export function setActiveHostElement(elementIndex: number | null = null) {
|
export function setActiveHostElement(elementIndex: number | null = null) {
|
||||||
if (getSelectedIndex() !== elementIndex) {
|
if (hasActiveElementFlag(ActiveElementFlags.RunExitFn)) {
|
||||||
if (hasActiveElementFlag(ActiveElementFlags.RunExitFn)) {
|
executeElementExitFn();
|
||||||
executeElementExitFn();
|
|
||||||
}
|
|
||||||
setSelectedIndex(elementIndex === null ? -1 : elementIndex);
|
|
||||||
instructionState.activeDirectiveId = 0;
|
|
||||||
}
|
}
|
||||||
|
setSelectedIndex(elementIndex === null ? -1 : elementIndex);
|
||||||
|
instructionState.lFrame.activeDirectiveId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function executeElementExitFn() {
|
export function executeElementExitFn() {
|
||||||
instructionState.elementExitFn !();
|
instructionState.elementExitFn !();
|
||||||
// TODO (matsko|misko): remove this unassignment once the state management of
|
instructionState.lFrame.selectedIndex &= ~ActiveElementFlags.RunExitFn;
|
||||||
// global variables are better managed.
|
|
||||||
instructionState.selectedIndex &= ~ActiveElementFlags.RunExitFn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -331,7 +348,7 @@ export function setElementExitFn(fn: () => void): void {
|
|||||||
* different set of directives).
|
* different set of directives).
|
||||||
*/
|
*/
|
||||||
export function getActiveDirectiveId() {
|
export function getActiveDirectiveId() {
|
||||||
return instructionState.activeDirectiveId;
|
return instructionState.lFrame.activeDirectiveId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -360,7 +377,7 @@ export function incrementActiveDirectiveId() {
|
|||||||
// directive uniqueId is not set anywhere--it is just incremented between
|
// directive uniqueId is not set anywhere--it is just incremented between
|
||||||
// each hostBindings call and is useful for helping instruction code
|
// each hostBindings call and is useful for helping instruction code
|
||||||
// uniquely determine which directive is currently active when executed.
|
// uniquely determine which directive is currently active when executed.
|
||||||
instructionState.activeDirectiveId += 1;
|
instructionState.lFrame.activeDirectiveId += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -375,44 +392,34 @@ export function incrementActiveDirectiveId() {
|
|||||||
* @codeGenApi
|
* @codeGenApi
|
||||||
*/
|
*/
|
||||||
export function ɵɵrestoreView(viewToRestore: OpaqueViewState) {
|
export function ɵɵrestoreView(viewToRestore: OpaqueViewState) {
|
||||||
instructionState.contextLView = viewToRestore as any as LView;
|
instructionState.lFrame.contextLView = viewToRestore as any as LView;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPreviousOrParentTNode(): TNode {
|
export function getPreviousOrParentTNode(): TNode {
|
||||||
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
|
return instructionState.lFrame.previousOrParentTNode;
|
||||||
return instructionState.previousOrParentTNode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setPreviousOrParentTNode(tNode: TNode, _isParent: boolean) {
|
export function setPreviousOrParentTNode(tNode: TNode, _isParent: boolean) {
|
||||||
instructionState.previousOrParentTNode = tNode;
|
instructionState.lFrame.previousOrParentTNode = tNode;
|
||||||
instructionState.isParent = _isParent;
|
instructionState.lFrame.isParent = _isParent;
|
||||||
}
|
|
||||||
|
|
||||||
export function setTNodeAndViewData(tNode: TNode, view: LView) {
|
|
||||||
ngDevMode && assertLViewOrUndefined(view);
|
|
||||||
instructionState.previousOrParentTNode = tNode;
|
|
||||||
instructionState.lView = view;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getIsParent(): boolean {
|
export function getIsParent(): boolean {
|
||||||
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
|
return instructionState.lFrame.isParent;
|
||||||
return instructionState.isParent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setIsNotParent(): void {
|
export function setIsNotParent(): void {
|
||||||
instructionState.isParent = false;
|
instructionState.lFrame.isParent = false;
|
||||||
}
|
}
|
||||||
export function setIsParent(): void {
|
export function setIsParent(): void {
|
||||||
instructionState.isParent = true;
|
instructionState.lFrame.isParent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getContextLView(): LView {
|
export function getContextLView(): LView {
|
||||||
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
|
return instructionState.lFrame.contextLView;
|
||||||
return instructionState.contextLView;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCheckNoChangesMode(): boolean {
|
export function getCheckNoChangesMode(): boolean {
|
||||||
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
|
|
||||||
return instructionState.checkNoChangesMode;
|
return instructionState.checkNoChangesMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,22 +429,63 @@ export function setCheckNoChangesMode(mode: boolean): void {
|
|||||||
|
|
||||||
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
|
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
|
||||||
export function getBindingRoot() {
|
export function getBindingRoot() {
|
||||||
return instructionState.bindingRootIndex;
|
const lFrame = instructionState.lFrame;
|
||||||
|
let index = lFrame.bindingRootIndex;
|
||||||
|
if (index === -1) {
|
||||||
|
const lView = lFrame.lView;
|
||||||
|
index = lFrame.bindingRootIndex = lView[BINDING_INDEX] = lView[TVIEW].bindingStartIndex;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setBindingRoot(value: number) {
|
export function setBindingRoot(value: number) {
|
||||||
instructionState.bindingRootIndex = value;
|
instructionState.lFrame.bindingRootIndex = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCurrentQueryIndex(): number {
|
export function getCurrentQueryIndex(): number {
|
||||||
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
|
return instructionState.lFrame.currentQueryIndex;
|
||||||
return instructionState.currentQueryIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setCurrentQueryIndex(value: number): void {
|
export function setCurrentQueryIndex(value: number): void {
|
||||||
instructionState.currentQueryIndex = value;
|
instructionState.lFrame.currentQueryIndex = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a light weight version of the `enterView` which is needed by the DI system.
|
||||||
|
* @param newView
|
||||||
|
* @param tNode
|
||||||
|
*/
|
||||||
|
export function enterDI(newView: LView, tNode: TNode) {
|
||||||
|
ngDevMode && assertLViewOrUndefined(newView);
|
||||||
|
const newLFrame = allocLFrame();
|
||||||
|
instructionState.lFrame = newLFrame;
|
||||||
|
newLFrame.previousOrParentTNode = tNode !;
|
||||||
|
newLFrame.lView = newView;
|
||||||
|
if (ngDevMode) {
|
||||||
|
// resetting for safety in dev mode only.
|
||||||
|
newLFrame.isParent = DEV_MODE_VALUE;
|
||||||
|
newLFrame.selectedIndex = DEV_MODE_VALUE;
|
||||||
|
newLFrame.contextLView = DEV_MODE_VALUE;
|
||||||
|
newLFrame.elementDepthCount = DEV_MODE_VALUE;
|
||||||
|
newLFrame.currentNamespace = DEV_MODE_VALUE;
|
||||||
|
newLFrame.currentSanitizer = DEV_MODE_VALUE;
|
||||||
|
newLFrame.currentDirectiveDef = DEV_MODE_VALUE;
|
||||||
|
newLFrame.activeDirectiveId = DEV_MODE_VALUE;
|
||||||
|
newLFrame.bindingRootIndex = DEV_MODE_VALUE;
|
||||||
|
newLFrame.currentQueryIndex = DEV_MODE_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const DEV_MODE_VALUE: any =
|
||||||
|
'Value indicating that DI is trying to read value which it should not need to know about.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a light weight version of the `leaveView` which is needed by the DI system.
|
||||||
|
*
|
||||||
|
* Because the implementation is same it is only an alias
|
||||||
|
*/
|
||||||
|
export const leaveDI = leaveView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Swap the current lView with a new lView.
|
* Swap the current lView with a new lView.
|
||||||
*
|
*
|
||||||
@ -447,27 +495,72 @@ export function setCurrentQueryIndex(value: number): void {
|
|||||||
* exited the state has to be restored
|
* exited the state has to be restored
|
||||||
*
|
*
|
||||||
* @param newView New lView to become active
|
* @param newView New lView to become active
|
||||||
* @param host Element to which the View is a child of
|
* @param tNode Element to which the View is a child of
|
||||||
* @returns the previously active lView;
|
* @returns the previously active lView;
|
||||||
*/
|
*/
|
||||||
export function selectView(newView: LView, hostTNode: TElementNode | TViewNode | null): LView {
|
export function enterView(newView: LView, tNode: TNode | null): void {
|
||||||
|
ngDevMode && assertLViewOrUndefined(newView);
|
||||||
|
const newLFrame = allocLFrame();
|
||||||
|
instructionState.lFrame = newLFrame;
|
||||||
|
newLFrame.previousOrParentTNode = tNode !;
|
||||||
|
newLFrame.isParent = true;
|
||||||
|
newLFrame.lView = newView;
|
||||||
|
newLFrame.selectedIndex = 0;
|
||||||
|
newLFrame.contextLView = newView !;
|
||||||
|
newLFrame.elementDepthCount = 0;
|
||||||
|
newLFrame.currentNamespace = null;
|
||||||
|
newLFrame.currentSanitizer = null;
|
||||||
|
newLFrame.currentDirectiveDef = null;
|
||||||
|
newLFrame.activeDirectiveId = 0;
|
||||||
|
newLFrame.bindingRootIndex = -1;
|
||||||
|
newLFrame.currentQueryIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates next free LFrame. This function tries to reuse the `LFrame`s to lower memory pressure.
|
||||||
|
*/
|
||||||
|
function allocLFrame() {
|
||||||
|
const currentLFrame = instructionState.lFrame;
|
||||||
|
const childLFrame = currentLFrame === null ? null : currentLFrame.child;
|
||||||
|
const newLFrame = childLFrame === null ? createLFrame(currentLFrame) : childLFrame;
|
||||||
|
return newLFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createLFrame(parent: LFrame | null): LFrame {
|
||||||
|
const lFrame: LFrame = {
|
||||||
|
previousOrParentTNode: null !, //
|
||||||
|
isParent: true, //
|
||||||
|
lView: null !, //
|
||||||
|
selectedIndex: 0, //
|
||||||
|
contextLView: null !, //
|
||||||
|
elementDepthCount: 0, //
|
||||||
|
currentNamespace: null, //
|
||||||
|
currentSanitizer: null, //
|
||||||
|
currentDirectiveDef: null, //
|
||||||
|
activeDirectiveId: 0, //
|
||||||
|
bindingRootIndex: -1, //
|
||||||
|
currentQueryIndex: 0, //
|
||||||
|
parent: parent !, //
|
||||||
|
child: null, //
|
||||||
|
};
|
||||||
|
parent !== null && (parent.child = lFrame); // link the new LFrame for reuse.
|
||||||
|
return lFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function leaveViewProcessExit() {
|
||||||
if (hasActiveElementFlag(ActiveElementFlags.RunExitFn)) {
|
if (hasActiveElementFlag(ActiveElementFlags.RunExitFn)) {
|
||||||
executeElementExitFn();
|
executeElementExitFn();
|
||||||
}
|
}
|
||||||
|
leaveView();
|
||||||
|
}
|
||||||
|
|
||||||
ngDevMode && assertLViewOrUndefined(newView);
|
export function leaveView() {
|
||||||
const oldView = instructionState.lView;
|
instructionState.lFrame = instructionState.lFrame.parent;
|
||||||
|
|
||||||
instructionState.previousOrParentTNode = hostTNode !;
|
|
||||||
instructionState.isParent = true;
|
|
||||||
|
|
||||||
instructionState.lView = instructionState.contextLView = newView;
|
|
||||||
return oldView;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function nextContextImpl<T = any>(level: number = 1): T {
|
export function nextContextImpl<T = any>(level: number = 1): T {
|
||||||
instructionState.contextLView = walkUpViews(level, instructionState.contextLView !);
|
instructionState.lFrame.contextLView = walkUpViews(level, instructionState.lFrame.contextLView !);
|
||||||
return instructionState.contextLView[CONTEXT] as T;
|
return instructionState.lFrame.contextLView[CONTEXT] as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
function walkUpViews(nestingLevel: number, currentView: LView): LView {
|
function walkUpViews(nestingLevel: number, currentView: LView): LView {
|
||||||
@ -481,17 +574,6 @@ function walkUpViews(nestingLevel: number, currentView: LView): LView {
|
|||||||
return currentView;
|
return currentView;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets the application state.
|
|
||||||
*/
|
|
||||||
export function resetComponentState() {
|
|
||||||
instructionState.isParent = false;
|
|
||||||
instructionState.previousOrParentTNode = null !;
|
|
||||||
instructionState.elementDepthCount = 0;
|
|
||||||
instructionState.bindingsEnabled = true;
|
|
||||||
setCurrentStyleSanitizer(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the most recent index passed to {@link select}
|
* Gets the most recent index passed to {@link select}
|
||||||
*
|
*
|
||||||
@ -499,7 +581,7 @@ export function resetComponentState() {
|
|||||||
* current `LView` to act on.
|
* current `LView` to act on.
|
||||||
*/
|
*/
|
||||||
export function getSelectedIndex() {
|
export function getSelectedIndex() {
|
||||||
return instructionState.selectedIndex >> ActiveElementFlags.Size;
|
return instructionState.lFrame.selectedIndex >> ActiveElementFlags.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -512,7 +594,7 @@ export function getSelectedIndex() {
|
|||||||
* run if and when the provided `index` value is different from the current selected index value.)
|
* run if and when the provided `index` value is different from the current selected index value.)
|
||||||
*/
|
*/
|
||||||
export function setSelectedIndex(index: number) {
|
export function setSelectedIndex(index: number) {
|
||||||
instructionState.selectedIndex = index << ActiveElementFlags.Size;
|
instructionState.lFrame.selectedIndex = index << ActiveElementFlags.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -522,7 +604,7 @@ export function setSelectedIndex(index: number) {
|
|||||||
* @codeGenApi
|
* @codeGenApi
|
||||||
*/
|
*/
|
||||||
export function ɵɵnamespaceSVG() {
|
export function ɵɵnamespaceSVG() {
|
||||||
instructionState.currentNamespace = 'http://www.w3.org/2000/svg';
|
instructionState.lFrame.currentNamespace = 'http://www.w3.org/2000/svg';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -531,7 +613,7 @@ export function ɵɵnamespaceSVG() {
|
|||||||
* @codeGenApi
|
* @codeGenApi
|
||||||
*/
|
*/
|
||||||
export function ɵɵnamespaceMathML() {
|
export function ɵɵnamespaceMathML() {
|
||||||
instructionState.currentNamespace = 'http://www.w3.org/1998/MathML/';
|
instructionState.lFrame.currentNamespace = 'http://www.w3.org/1998/MathML/';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -549,15 +631,15 @@ export function ɵɵnamespaceHTML() {
|
|||||||
* `createElement` rather than `createElementNS`.
|
* `createElement` rather than `createElementNS`.
|
||||||
*/
|
*/
|
||||||
export function namespaceHTMLInternal() {
|
export function namespaceHTMLInternal() {
|
||||||
instructionState.currentNamespace = null;
|
instructionState.lFrame.currentNamespace = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNamespace(): string|null {
|
export function getNamespace(): string|null {
|
||||||
return instructionState.currentNamespace;
|
return instructionState.lFrame.currentNamespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setCurrentStyleSanitizer(sanitizer: StyleSanitizeFn | null) {
|
export function setCurrentStyleSanitizer(sanitizer: StyleSanitizeFn | null) {
|
||||||
instructionState.currentSanitizer = sanitizer;
|
instructionState.lFrame.currentSanitizer = sanitizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resetCurrentStyleSanitizer() {
|
export function resetCurrentStyleSanitizer() {
|
||||||
@ -565,5 +647,8 @@ export function resetCurrentStyleSanitizer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getCurrentStyleSanitizer() {
|
export function getCurrentStyleSanitizer() {
|
||||||
return instructionState.currentSanitizer;
|
// TODO(misko): This should throw when there is no LView, but it turns out we can get here from
|
||||||
|
// `NodeStyleDebug` hence we return `null`. This should be fixed
|
||||||
|
const lFrame = instructionState.lFrame;
|
||||||
|
return lFrame === null ? null : lFrame.currentSanitizer;
|
||||||
}
|
}
|
||||||
|
@ -2105,7 +2105,7 @@ describe('styling', () => {
|
|||||||
expect(readyChild).toBeTruthy();
|
expect(readyChild).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
onlyInIvy('only ivy allows for multiple styles/classes to be balanaced across directives')
|
onlyInIvy('only ivy allows for multiple styles/classes to be balanced across directives')
|
||||||
.it('should allow various duplicate properties to be defined in various styling maps within the template and directive styling bindings',
|
.it('should allow various duplicate properties to be defined in various styling maps within the template and directive styling bindings',
|
||||||
() => {
|
() => {
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -155,6 +155,9 @@
|
|||||||
{
|
{
|
||||||
"name": "addToViewTree"
|
"name": "addToViewTree"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "allocLFrame"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "allocStylingMapArray"
|
"name": "allocStylingMapArray"
|
||||||
},
|
},
|
||||||
@ -185,6 +188,9 @@
|
|||||||
{
|
{
|
||||||
"name": "createDirectivesInstances"
|
"name": "createDirectivesInstances"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "createLFrame"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "createLView"
|
"name": "createLView"
|
||||||
},
|
},
|
||||||
@ -227,6 +233,12 @@
|
|||||||
{
|
{
|
||||||
"name": "elementCreate"
|
"name": "elementCreate"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "enterDI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "enterView"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "executeCheckHooks"
|
"name": "executeCheckHooks"
|
||||||
},
|
},
|
||||||
@ -479,6 +491,15 @@
|
|||||||
{
|
{
|
||||||
"name": "isStylingValueDefined"
|
"name": "isStylingValueDefined"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "leaveDI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "leaveView"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "leaveViewProcessExit"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "locateHostElement"
|
"name": "locateHostElement"
|
||||||
},
|
},
|
||||||
@ -488,9 +509,6 @@
|
|||||||
{
|
{
|
||||||
"name": "matchTemplateAttribute"
|
"name": "matchTemplateAttribute"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "namespaceHTMLInternal"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "nativeAppendChild"
|
"name": "nativeAppendChild"
|
||||||
},
|
},
|
||||||
@ -560,9 +578,6 @@
|
|||||||
{
|
{
|
||||||
"name": "renderView"
|
"name": "renderView"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "resetComponentState"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "resetPreOrderHookFlags"
|
"name": "resetPreOrderHookFlags"
|
||||||
},
|
},
|
||||||
@ -581,9 +596,6 @@
|
|||||||
{
|
{
|
||||||
"name": "selectIndexInternal"
|
"name": "selectIndexInternal"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "selectView"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "setActiveHostElement"
|
"name": "setActiveHostElement"
|
||||||
},
|
},
|
||||||
@ -599,9 +611,6 @@
|
|||||||
{
|
{
|
||||||
"name": "setCurrentQueryIndex"
|
"name": "setCurrentQueryIndex"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "setCurrentStyleSanitizer"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "setDirectiveStylingInput"
|
"name": "setDirectiveStylingInput"
|
||||||
},
|
},
|
||||||
@ -635,9 +644,6 @@
|
|||||||
{
|
{
|
||||||
"name": "setStyle"
|
"name": "setStyle"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "setTNodeAndViewData"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "setUpAttributes"
|
"name": "setUpAttributes"
|
||||||
},
|
},
|
||||||
|
@ -134,6 +134,9 @@
|
|||||||
{
|
{
|
||||||
"name": "addToViewTree"
|
"name": "addToViewTree"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "allocLFrame"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "appendChild"
|
"name": "appendChild"
|
||||||
},
|
},
|
||||||
@ -152,6 +155,9 @@
|
|||||||
{
|
{
|
||||||
"name": "callHooks"
|
"name": "callHooks"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "createLFrame"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "createLView"
|
"name": "createLView"
|
||||||
},
|
},
|
||||||
@ -188,6 +194,12 @@
|
|||||||
{
|
{
|
||||||
"name": "domRendererFactory3"
|
"name": "domRendererFactory3"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "enterDI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "enterView"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "executeCheckHooks"
|
"name": "executeCheckHooks"
|
||||||
},
|
},
|
||||||
@ -350,15 +362,21 @@
|
|||||||
{
|
{
|
||||||
"name": "isRootView"
|
"name": "isRootView"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "leaveDI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "leaveView"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "leaveViewProcessExit"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "locateHostElement"
|
"name": "locateHostElement"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "markAsComponentHost"
|
"name": "markAsComponentHost"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "namespaceHTMLInternal"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "nativeAppendChild"
|
"name": "nativeAppendChild"
|
||||||
},
|
},
|
||||||
@ -410,18 +428,12 @@
|
|||||||
{
|
{
|
||||||
"name": "renderView"
|
"name": "renderView"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "resetComponentState"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "resetPreOrderHookFlags"
|
"name": "resetPreOrderHookFlags"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "selectIndexInternal"
|
"name": "selectIndexInternal"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "selectView"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "setActiveHostElement"
|
"name": "setActiveHostElement"
|
||||||
},
|
},
|
||||||
@ -434,9 +446,6 @@
|
|||||||
{
|
{
|
||||||
"name": "setCurrentQueryIndex"
|
"name": "setCurrentQueryIndex"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "setCurrentStyleSanitizer"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "setHostBindings"
|
"name": "setHostBindings"
|
||||||
},
|
},
|
||||||
@ -455,9 +464,6 @@
|
|||||||
{
|
{
|
||||||
"name": "setSelectedIndex"
|
"name": "setSelectedIndex"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "setTNodeAndViewData"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "stringifyForError"
|
"name": "stringifyForError"
|
||||||
},
|
},
|
||||||
|
@ -362,6 +362,9 @@
|
|||||||
{
|
{
|
||||||
"name": "addToViewTree"
|
"name": "addToViewTree"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "allocLFrame"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "allocStylingMapArray"
|
"name": "allocStylingMapArray"
|
||||||
},
|
},
|
||||||
@ -461,6 +464,9 @@
|
|||||||
{
|
{
|
||||||
"name": "createLContext"
|
"name": "createLContext"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "createLFrame"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "createLView"
|
"name": "createLView"
|
||||||
},
|
},
|
||||||
@ -527,6 +533,12 @@
|
|||||||
{
|
{
|
||||||
"name": "elementPropertyInternal"
|
"name": "elementPropertyInternal"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "enterDI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "enterView"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "executeCheckHooks"
|
"name": "executeCheckHooks"
|
||||||
},
|
},
|
||||||
@ -977,6 +989,15 @@
|
|||||||
{
|
{
|
||||||
"name": "iterateListLike"
|
"name": "iterateListLike"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "leaveDI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "leaveView"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "leaveViewProcessExit"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "listenerInternal"
|
"name": "listenerInternal"
|
||||||
},
|
},
|
||||||
@ -1022,9 +1043,6 @@
|
|||||||
{
|
{
|
||||||
"name": "matchTemplateAttribute"
|
"name": "matchTemplateAttribute"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "namespaceHTMLInternal"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "nativeAppendChild"
|
"name": "nativeAppendChild"
|
||||||
},
|
},
|
||||||
@ -1139,9 +1157,6 @@
|
|||||||
{
|
{
|
||||||
"name": "renderView"
|
"name": "renderView"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "resetComponentState"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "resetCurrentStyleSanitizer"
|
"name": "resetCurrentStyleSanitizer"
|
||||||
},
|
},
|
||||||
@ -1175,9 +1190,6 @@
|
|||||||
{
|
{
|
||||||
"name": "selectIndexInternal"
|
"name": "selectIndexInternal"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "selectView"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "setActiveElementFlag"
|
"name": "setActiveElementFlag"
|
||||||
},
|
},
|
||||||
@ -1247,9 +1259,6 @@
|
|||||||
{
|
{
|
||||||
"name": "setStyle"
|
"name": "setStyle"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "setTNodeAndViewData"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "setUpAttributes"
|
"name": "setUpAttributes"
|
||||||
},
|
},
|
||||||
|
@ -17,7 +17,7 @@ import {TNODE} from '../../src/render3/interfaces/injector';
|
|||||||
import {TNodeType} from '../../src/render3/interfaces/node';
|
import {TNodeType} from '../../src/render3/interfaces/node';
|
||||||
import {isProceduralRenderer} from '../../src/render3/interfaces/renderer';
|
import {isProceduralRenderer} from '../../src/render3/interfaces/renderer';
|
||||||
import {LViewFlags, TVIEW} from '../../src/render3/interfaces/view';
|
import {LViewFlags, TVIEW} from '../../src/render3/interfaces/view';
|
||||||
import {selectView} from '../../src/render3/state';
|
import {enterView, leaveViewProcessExit} from '../../src/render3/state';
|
||||||
|
|
||||||
import {getRendererFactory2} from './imported_renderer2';
|
import {getRendererFactory2} from './imported_renderer2';
|
||||||
import {ComponentFixture, createComponent, createDirective} from './render_util';
|
import {ComponentFixture, createComponent, createDirective} from './render_util';
|
||||||
@ -225,7 +225,7 @@ describe('di', () => {
|
|||||||
const contentView = createLView(
|
const contentView = createLView(
|
||||||
null, createTView(-1, null, 1, 0, null, null, null, null, null), null,
|
null, createTView(-1, null, 1, 0, null, null, null, null, null), null,
|
||||||
LViewFlags.CheckAlways, null, null, {} as any, {} as any);
|
LViewFlags.CheckAlways, null, null, {} as any, {} as any);
|
||||||
const oldView = selectView(contentView, null);
|
enterView(contentView, null);
|
||||||
try {
|
try {
|
||||||
const parentTNode =
|
const parentTNode =
|
||||||
getOrCreateTNode(contentView[TVIEW], null, 0, TNodeType.Element, null, null);
|
getOrCreateTNode(contentView[TVIEW], null, 0, TNodeType.Element, null, null);
|
||||||
@ -237,7 +237,7 @@ describe('di', () => {
|
|||||||
const injector = getOrCreateNodeInjectorForNode(parentTNode, contentView);
|
const injector = getOrCreateNodeInjectorForNode(parentTNode, contentView);
|
||||||
expect(injector).not.toEqual(-1);
|
expect(injector).not.toEqual(-1);
|
||||||
} finally {
|
} finally {
|
||||||
selectView(oldView, null);
|
leaveViewProcessExit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -9,7 +9,6 @@ import {ɵɵdefineDirective, ɵɵelementEnd, ɵɵelementStart, ɵɵtext} from '.
|
|||||||
import {createTNode, createTView} from '../../../../src/render3/instructions/shared';
|
import {createTNode, createTView} from '../../../../src/render3/instructions/shared';
|
||||||
import {RenderFlags} from '../../../../src/render3/interfaces/definition';
|
import {RenderFlags} from '../../../../src/render3/interfaces/definition';
|
||||||
import {TNodeType, TViewNode} from '../../../../src/render3/interfaces/node';
|
import {TNodeType, TViewNode} from '../../../../src/render3/interfaces/node';
|
||||||
import {resetComponentState} from '../../../../src/render3/state';
|
|
||||||
import {createBenchmark} from '../micro_bench';
|
import {createBenchmark} from '../micro_bench';
|
||||||
import {createAndRenderLView} from '../setup';
|
import {createAndRenderLView} from '../setup';
|
||||||
|
|
||||||
@ -78,9 +77,6 @@ const embeddedTView = createTView(
|
|||||||
-1, testTemplate, 21, 10, [Tooltip.ɵdir], null, null, null,
|
-1, testTemplate, 21, 10, [Tooltip.ɵdir], null, null, null,
|
||||||
[['position', 'top', 3, 'tooltip']]);
|
[['position', 'top', 3, 'tooltip']]);
|
||||||
|
|
||||||
// initialize global state
|
|
||||||
resetComponentState();
|
|
||||||
|
|
||||||
// create view once so we don't profile first template pass
|
// create view once so we don't profile first template pass
|
||||||
createAndRenderLView(null, embeddedTView, viewTNode);
|
createAndRenderLView(null, embeddedTView, viewTNode);
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ import {createTNode, createTView} from '../../../../src/render3/instructions/sha
|
|||||||
import {ɵɵtext} from '../../../../src/render3/instructions/text';
|
import {ɵɵtext} from '../../../../src/render3/instructions/text';
|
||||||
import {RenderFlags} from '../../../../src/render3/interfaces/definition';
|
import {RenderFlags} from '../../../../src/render3/interfaces/definition';
|
||||||
import {TNodeType, TViewNode} from '../../../../src/render3/interfaces/node';
|
import {TNodeType, TViewNode} from '../../../../src/render3/interfaces/node';
|
||||||
import {resetComponentState} from '../../../../src/render3/state';
|
|
||||||
import {createBenchmark} from '../micro_bench';
|
import {createBenchmark} from '../micro_bench';
|
||||||
import {createAndRenderLView} from '../setup';
|
import {createAndRenderLView} from '../setup';
|
||||||
|
|
||||||
@ -69,9 +68,6 @@ const embeddedTView = createTView(-1, testTemplate, 21, 0, null, null, null, nul
|
|||||||
['name1', 'value1', 'name2', 'value2', 'name3', 'value3', 'name4', 'value4', 'name5', 'value5']
|
['name1', 'value1', 'name2', 'value2', 'name3', 'value3', 'name4', 'value4', 'name5', 'value5']
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// initialize global state
|
|
||||||
resetComponentState();
|
|
||||||
|
|
||||||
// create view once so we don't profile first template pass
|
// create view once so we don't profile first template pass
|
||||||
createAndRenderLView(null, embeddedTView, viewTNode);
|
createAndRenderLView(null, embeddedTView, viewTNode);
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ import {ɵɵlistener} from '../../../../src/render3/instructions/listener';
|
|||||||
import {createTNode, createTView} from '../../../../src/render3/instructions/shared';
|
import {createTNode, createTView} from '../../../../src/render3/instructions/shared';
|
||||||
import {RenderFlags} from '../../../../src/render3/interfaces/definition';
|
import {RenderFlags} from '../../../../src/render3/interfaces/definition';
|
||||||
import {TNodeType, TViewNode} from '../../../../src/render3/interfaces/node';
|
import {TNodeType, TViewNode} from '../../../../src/render3/interfaces/node';
|
||||||
import {resetComponentState} from '../../../../src/render3/state';
|
|
||||||
import {createBenchmark} from '../micro_bench';
|
import {createBenchmark} from '../micro_bench';
|
||||||
import {createAndRenderLView} from '../setup';
|
import {createAndRenderLView} from '../setup';
|
||||||
|
|
||||||
@ -79,9 +78,6 @@ const viewTNode = createTNode(null !, null, TNodeType.View, -1, null, null) as T
|
|||||||
const embeddedTView =
|
const embeddedTView =
|
||||||
createTView(-1, testTemplate, 11, 0, null, null, null, null, [[3, 'click', 'input']]);
|
createTView(-1, testTemplate, 11, 0, null, null, null, null, [[3, 'click', 'input']]);
|
||||||
|
|
||||||
// initialize global state
|
|
||||||
resetComponentState();
|
|
||||||
|
|
||||||
// create view once so we don't profile first template pass
|
// create view once so we don't profile first template pass
|
||||||
createAndRenderLView(null, embeddedTView, viewTNode);
|
createAndRenderLView(null, embeddedTView, viewTNode);
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ const noopChangeDetection = createBenchmark('noop change detection');
|
|||||||
const refreshTime = noopChangeDetection('refresh');
|
const refreshTime = noopChangeDetection('refresh');
|
||||||
|
|
||||||
// run change detection in the update mode
|
// run change detection in the update mode
|
||||||
console.profile('noop_refresh');
|
console.profile('noop_change_detection');
|
||||||
while (refreshTime()) {
|
while (refreshTime()) {
|
||||||
refreshView(rootLView, rootTView, null, null);
|
refreshView(rootLView, rootTView, null, null);
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ import {ViewContainerRef} from '@angular/core/src/linker/view_container_ref';
|
|||||||
import {Renderer2} from '@angular/core/src/render/api';
|
import {Renderer2} from '@angular/core/src/render/api';
|
||||||
import {createLView, createTView, getOrCreateTNode, getOrCreateTView, renderComponentOrTemplate} from '@angular/core/src/render3/instructions/shared';
|
import {createLView, createTView, getOrCreateTNode, getOrCreateTView, renderComponentOrTemplate} from '@angular/core/src/render3/instructions/shared';
|
||||||
import {TAttributes, TNodeType} from '@angular/core/src/render3/interfaces/node';
|
import {TAttributes, TNodeType} from '@angular/core/src/render3/interfaces/node';
|
||||||
import {getLView, resetComponentState, selectView} from '@angular/core/src/render3/state';
|
import {enterView, getLView} from '@angular/core/src/render3/state';
|
||||||
import {stringifyElement} from '@angular/platform-browser/testing/src/browser_util';
|
import {stringifyElement} from '@angular/platform-browser/testing/src/browser_util';
|
||||||
|
|
||||||
import {SWITCH_CHANGE_DETECTOR_REF_FACTORY__POST_R3__ as R3_CHANGE_DETECTOR_REF_FACTORY} from '../../src/change_detection/change_detector_ref';
|
import {SWITCH_CHANGE_DETECTOR_REF_FACTORY__POST_R3__ as R3_CHANGE_DETECTOR_REF_FACTORY} from '../../src/change_detection/change_detector_ref';
|
||||||
@ -32,7 +32,7 @@ import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveT
|
|||||||
import {DirectiveDefList, DirectiveDefListOrFactory, DirectiveTypesOrFactory, HostBindingsFunction, PipeDef, PipeDefList, PipeDefListOrFactory, PipeTypesOrFactory} from '../../src/render3/interfaces/definition';
|
import {DirectiveDefList, DirectiveDefListOrFactory, DirectiveTypesOrFactory, HostBindingsFunction, PipeDef, PipeDefList, PipeDefListOrFactory, PipeTypesOrFactory} from '../../src/render3/interfaces/definition';
|
||||||
import {PlayerHandler} from '../../src/render3/interfaces/player';
|
import {PlayerHandler} from '../../src/render3/interfaces/player';
|
||||||
import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, RendererFactory3, RendererStyleFlags3, domRendererFactory3} from '../../src/render3/interfaces/renderer';
|
import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, RendererFactory3, RendererStyleFlags3, domRendererFactory3} from '../../src/render3/interfaces/renderer';
|
||||||
import {HEADER_OFFSET, LView, LViewFlags, TVIEW, T_HOST} from '../../src/render3/interfaces/view';
|
import {HEADER_OFFSET, LView, LViewFlags, T_HOST} from '../../src/render3/interfaces/view';
|
||||||
import {destroyLView} from '../../src/render3/node_manipulation';
|
import {destroyLView} from '../../src/render3/node_manipulation';
|
||||||
import {getRootView} from '../../src/render3/util/view_traversal_utils';
|
import {getRootView} from '../../src/render3/util/view_traversal_utils';
|
||||||
import {Sanitizer} from '../../src/sanitization/sanitizer';
|
import {Sanitizer} from '../../src/sanitization/sanitizer';
|
||||||
@ -251,7 +251,6 @@ export function renderTemplate<T>(
|
|||||||
directives?: DirectiveDefListOrFactory | null, pipes?: PipeDefListOrFactory | null,
|
directives?: DirectiveDefListOrFactory | null, pipes?: PipeDefListOrFactory | null,
|
||||||
sanitizer?: Sanitizer | null, consts?: TAttributes[]): LView {
|
sanitizer?: Sanitizer | null, consts?: TAttributes[]): LView {
|
||||||
if (componentView === null) {
|
if (componentView === null) {
|
||||||
resetComponentState();
|
|
||||||
const renderer = providedRendererFactory.createRenderer(null, null);
|
const renderer = providedRendererFactory.createRenderer(null, null);
|
||||||
|
|
||||||
// We need to create a root view so it's possible to look up the host element through its index
|
// We need to create a root view so it's possible to look up the host element through its index
|
||||||
@ -259,7 +258,7 @@ export function renderTemplate<T>(
|
|||||||
const hostLView = createLView(
|
const hostLView = createLView(
|
||||||
null, tView, {}, LViewFlags.CheckAlways | LViewFlags.IsRoot, null, null,
|
null, tView, {}, LViewFlags.CheckAlways | LViewFlags.IsRoot, null, null,
|
||||||
providedRendererFactory, renderer);
|
providedRendererFactory, renderer);
|
||||||
selectView(hostLView, null); // SUSPECT! why do we need to enter the View?
|
enterView(hostLView, null);
|
||||||
|
|
||||||
const def: ComponentDef<any> = ɵɵdefineComponent({
|
const def: ComponentDef<any> = ɵɵdefineComponent({
|
||||||
selectors: [],
|
selectors: [],
|
||||||
|
@ -8,8 +8,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {SECURITY_SCHEMA} from '@angular/compiler/src/schema/dom_security_schema';
|
import {SECURITY_SCHEMA} from '@angular/compiler/src/schema/dom_security_schema';
|
||||||
import {HEADER_OFFSET, LView} from '@angular/core/src/render3/interfaces/view';
|
import {LView} from '@angular/core/src/render3/interfaces/view';
|
||||||
import {setTNodeAndViewData} from '@angular/core/src/render3/state';
|
import {enterView, leaveView} from '@angular/core/src/render3/state';
|
||||||
|
|
||||||
import {bypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript, bypassSanitizationTrustStyle, bypassSanitizationTrustUrl} from '../../src/sanitization/bypass';
|
import {bypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript, bypassSanitizationTrustStyle, bypassSanitizationTrustUrl} from '../../src/sanitization/bypass';
|
||||||
import {getUrlSanitizer, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl, ɵɵsanitizeUrlOrResourceUrl} from '../../src/sanitization/sanitization';
|
import {getUrlSanitizer, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl, ɵɵsanitizeUrlOrResourceUrl} from '../../src/sanitization/sanitization';
|
||||||
@ -20,8 +20,8 @@ function fakeLView(): LView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('sanitization', () => {
|
describe('sanitization', () => {
|
||||||
beforeEach(() => setTNodeAndViewData(null !, fakeLView()));
|
beforeEach(() => enterView(fakeLView(), null));
|
||||||
afterEach(() => setTNodeAndViewData(null !, null !));
|
afterEach(() => leaveView());
|
||||||
class Wrap {
|
class Wrap {
|
||||||
constructor(private value: string) {}
|
constructor(private value: string) {}
|
||||||
toString() { return this.value; }
|
toString() { return this.value; }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user