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:
Miško Hevery
2019-10-24 14:42:15 -07:00
committed by Andrew Kushnir
parent 9ea3430a5b
commit 09a2bb839f
19 changed files with 327 additions and 259 deletions
+2 -2
View File
@@ -12,7 +12,7 @@
"master": {
"uncompressed": {
"runtime-es2015": 1485,
"main-es2015": 14440,
"main-es2015": 14678,
"polyfills-es2015": 36808
}
}
@@ -64,4 +64,4 @@
}
}
}
}
}
+3 -8
View File
@@ -23,7 +23,7 @@ import {TElementNode, TNode, TNodeType} from './interfaces/node';
import {PlayerHandler} from './interfaces/player';
import {RElement, Renderer3, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
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 {defaultScheduler, stringifyForError} from './util/misc_utils';
import {getRootContext} from './util/view_traversal_utils';
@@ -111,10 +111,6 @@ export function renderComponent<T>(
ngDevMode && publishDefaultGlobalUtils();
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 sanitizer = opts.sanitizer || null;
const componentDef = getComponentDef<T>(componentType) !;
@@ -133,7 +129,7 @@ export function renderComponent<T>(
null, rootTView, rootContext, rootFlags, null, null, rendererFactory, renderer, undefined,
opts.injector || null);
const oldView = selectView(rootView, null);
enterView(rootView, null);
let component: T;
try {
@@ -149,7 +145,7 @@ export function renderComponent<T>(
refreshView(rootView, rootTView, null, null);
} finally {
selectView(oldView, null);
leaveView();
if (rendererFactory.end) rendererFactory.end();
}
@@ -170,7 +166,6 @@ export function renderComponent<T>(
export function createRootComponentView(
rNode: RElement | null, def: ComponentDef<any>, rootView: LView,
rendererFactory: RendererFactory3, renderer: Renderer3, sanitizer?: Sanitizer | null): LView {
resetComponentState();
const tView = rootView[TVIEW];
ngDevMode && assertDataInRange(rootView, 0 + HEADER_OFFSET);
rootView[0 + HEADER_OFFSET] = rNode;
+7 -6
View File
@@ -29,7 +29,7 @@ import {ComponentDef} from './interfaces/definition';
import {TContainerNode, TElementContainerNode, TElementNode} from './interfaces/node';
import {RNode, RendererFactory3, domRendererFactory3, isProceduralRenderer} from './interfaces/renderer';
import {LView, LViewFlags, TVIEW} from './interfaces/view';
import {namespaceHTMLInternal, selectView} from './state';
import {enterView, leaveView} from './state';
import {defaultScheduler} from './util/misc_utils';
import {getTNode} from './util/view_utils';
import {createElementRef} from './view_engine_compatibility';
@@ -133,9 +133,6 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
rootViewInjector.get(RendererFactory2, domRendererFactory3) as RendererFactory3;
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 ?
locateHostElement(rendererFactory, rootSelectorOrNode) :
elementCreate(this.selector, rendererFactory.createRenderer(null, this.componentDef), null);
@@ -167,7 +164,11 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
rootViewInjector);
// 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 tElementNode: TElementNode;
@@ -194,7 +195,7 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
renderView(rootLView, rootTView, null);
} finally {
selectView(oldLView, null);
leaveView();
}
const componentRef = new ComponentRef(
+10 -14
View File
@@ -10,7 +10,7 @@ import {isForwardRef, resolveForwardRef} from '../di/forward_ref';
import {InjectionToken} from '../di/injection_token';
import {Injector} from '../di/injector';
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 {Type} from '../interface/type';
import {assertDefined, assertEqual} from '../util/assert';
@@ -19,11 +19,11 @@ import {getFactoryDef} from './definition';
import {NG_ELEMENT_ID, NG_FACTORY_DEF} from './fields';
import {DirectiveDef, FactoryFn} from './interfaces/definition';
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 {DECLARATION_VIEW, INJECTOR, LView, TData, TVIEW, TView, T_HOST} from './interfaces/view';
import {assertNodeOfPossibleTypes} from './node_assert';
import {getLView, getPreviousOrParentTNode, setTNodeAndViewData} from './state';
import {enterDI, leaveDI} from './state';
import {isNameOnlyAttributeMarker} from './util/attrs_utils';
import {getParentInjectorIndex, getParentInjectorView, hasParentInjector} from './util/injector_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
// so just call the factory function to create it.
if (typeof bloomHash === 'function') {
const savePreviousOrParentTNode = getPreviousOrParentTNode();
const saveLView = getLView();
setTNodeAndViewData(tNode, lView);
enterDI(lView, tNode);
try {
const value = bloomHash();
if (value == null && !(flags & InjectFlags.Optional)) {
@@ -345,7 +343,7 @@ export function getOrCreateInjectable<T>(
return value;
}
} finally {
setTNodeAndViewData(savePreviousOrParentTNode, saveLView);
leaveDI();
}
} else if (typeof bloomHash == 'number') {
if (bloomHash === -1) {
@@ -530,8 +528,8 @@ export function locateDirectiveOrProvider<T>(
* instantiates the `injectable` and caches the value.
*/
export function getNodeInjectable(
tData: TData, lData: LView, index: number, tNode: TElementNode): any {
let value = lData[index];
tData: TData, lView: LView, index: number, tNode: TElementNode): any {
let value = lView[index];
if (isFactory(value)) {
const factory: NodeInjectorFactory = value;
if (factory.resolving) {
@@ -543,16 +541,14 @@ export function getNodeInjectable(
if (factory.injectImpl) {
previousInjectImplementation = setInjectImplementation(factory.injectImpl);
}
const savePreviousOrParentTNode = getPreviousOrParentTNode();
const saveLView = getLView();
setTNodeAndViewData(tNode, lData);
enterDI(lView, tNode);
try {
value = lData[index] = factory.factory(undefined, tData, lData, tNode);
value = lView[index] = factory.factory(undefined, tData, lView, tNode);
} finally {
if (factory.injectImpl) setInjectImplementation(previousInjectImplementation);
setIncludeViewProviders(previousIncludeViewProviders);
factory.resolving = false;
setTNodeAndViewData(savePreviousOrParentTNode, saveLView);
leaveDI();
}
}
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 {assertNodeType} from '../node_assert';
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 {assignTViewNodeToLView, createLView, createTView, refreshView, renderView} from './shared';
/**
* Marks the start of an embedded view.
*
@@ -42,7 +42,7 @@ export function ɵɵembeddedViewStart(viewBlockId: number, decls: number, vars:
if (viewToRender) {
setIsParent();
selectView(viewToRender, viewToRender[TVIEW].node);
enterView(viewToRender, viewToRender[TVIEW].node);
} else {
// When we create a new LView, we always reset the state of the instructions.
viewToRender = createLView(
@@ -52,7 +52,7 @@ export function ɵɵembeddedViewStart(viewBlockId: number, decls: number, vars:
const tParentNode = getIsParent() ? previousOrParentTNode :
previousOrParentTNode && previousOrParentTNode.parent;
assignTViewNodeToLView(viewToRender[TVIEW], tParentNode, viewBlockId, viewToRender);
selectView(viewToRender, viewToRender[TVIEW].node);
enterView(viewToRender, viewToRender[TVIEW].node);
}
if (lContainer) {
if (isCreationMode(viewToRender)) {
@@ -138,6 +138,6 @@ export function ɵɵembeddedViewEnd(): void {
const lContainer = lView[PARENT] as LContainer;
ngDevMode && assertLContainerOrUndefined(lContainer);
selectView(lContainer[PARENT] !, null);
leaveViewProcessExit();
setPreviousOrParentTNode(viewHost !, false);
}
@@ -17,8 +17,11 @@ import {CLEANUP, FLAGS, LView, LViewFlags, RENDERER, TVIEW} from '../interfaces/
import {assertNodeOfPossibleTypes} from '../node_assert';
import {getLView, getPreviousOrParentTNode} from '../state';
import {getComponentLViewByIndex, getNativeByTNode, unwrapRNode} from '../util/view_utils';
import {getCleanup, handleError, loadComponentRenderer, markViewDirty} from './shared';
/**
* Adds an event listener to the current node.
*
@@ -213,7 +216,7 @@ function listenerInternal(
}
function executeListenerWithErrorHandling(
lView: LView, listenerFn: (e?: any) => any, e: any): boolean {
lView: LView, tNode: TNode, listenerFn: (e?: any) => any, e: any): boolean {
try {
// Only explicitly returning false from a listener should preventDefault
return listenerFn(e) !== false;
@@ -256,13 +259,13 @@ function wrapListener(
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
// their presence and invoke as needed.
let nextListenerFn = (<any>wrapListenerIn_markDirtyAndPreventDefault).__ngNextListenerFn__;
while (nextListenerFn) {
// 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__;
}
@@ -15,7 +15,7 @@ import {createNamedArrayType} from '../../util/named_array_type';
import {initNgDevMode} from '../../util/ng_dev_mode';
import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../../util/ng_reflect';
import {assertFirstTemplatePass, assertLView} from '../assert';
import {attachPatchData, getComponentViewByInstance} from '../context_discovery';
import {attachPatchData} from '../context_discovery';
import {getFactoryDef} from '../definition';
import {diPublicInInjector, getNodeInjectable, getOrCreateNodeInjectorForNode} from '../di';
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 {assertNodeOfPossibleTypes} from '../node_assert';
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 {NO_CHANGE} from '../tokens';
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 {
ngDevMode && assertEqual(isCreationMode(lView), true, 'Should be run in creation mode');
const oldView = selectView(lView, lView[T_HOST]);
enterView(lView, lView[T_HOST]);
try {
const viewQuery = tView.viewQuery;
if (viewQuery !== null) {
@@ -357,7 +357,7 @@ export function renderView<T>(lView: LView, tView: TView, context: T): void {
} finally {
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>(
lView: LView, tView: TView, templateFn: ComponentTemplate<{}>| null, context: T) {
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];
try {
resetPreOrderHookFlags(lView);
@@ -463,7 +463,7 @@ export function refreshView<T>(
} finally {
lView[FLAGS] &= ~(LViewFlags.Dirty | LViewFlags.FirstLViewPass);
selectView(oldView, null);
leaveViewProcessExit();
}
}
@@ -472,8 +472,6 @@ export function renderComponentOrTemplate<T>(
const rendererFactory = hostView[RENDERER_FACTORY];
const normalExecutionPath = !getCheckNoChangesMode();
const creationModeIsActive = isCreationMode(hostView);
const previousOrParentTNode = getPreviousOrParentTNode();
const isParent = getIsParent();
try {
if (normalExecutionPath && !creationModeIsActive && rendererFactory.begin) {
rendererFactory.begin();
@@ -487,13 +485,11 @@ export function renderComponentOrTemplate<T>(
if (normalExecutionPath && !creationModeIsActive && rendererFactory.end) {
rendererFactory.end();
}
setPreviousOrParentTNode(previousOrParentTNode, isParent);
}
}
function executeTemplate<T>(
lView: LView, templateFn: ComponentTemplate<T>, rf: RenderFlags, context: T) {
namespaceHTMLInternal();
const prevSelectedIndex = getSelectedIndex();
try {
setActiveHostElement(null);
@@ -1659,9 +1655,6 @@ export function tickRootContext(rootContext: RootContext) {
export function detectChangesInternal<T>(view: LView, context: T) {
const rendererFactory = view[RENDERER_FACTORY];
const previousOrParentTNode = getPreviousOrParentTNode();
const isParent = getIsParent();
if (rendererFactory.begin) rendererFactory.begin();
try {
const tView = view[TVIEW];
@@ -1671,7 +1664,6 @@ export function detectChangesInternal<T>(view: LView, context: T) {
throw error;
} finally {
if (rendererFactory.end) rendererFactory.end();
setPreviousOrParentTNode(previousOrParentTNode, isParent);
}
}
@@ -1684,18 +1676,6 @@ export function detectChangesInRootView(lView: LView): void {
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) {
setCheckNoChangesMode(true);
try {
File diff suppressed because it is too large Load Diff
@@ -2105,7 +2105,7 @@ describe('styling', () => {
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',
() => {
@Component({
@@ -155,6 +155,9 @@
{
"name": "addToViewTree"
},
{
"name": "allocLFrame"
},
{
"name": "allocStylingMapArray"
},
@@ -185,6 +188,9 @@
{
"name": "createDirectivesInstances"
},
{
"name": "createLFrame"
},
{
"name": "createLView"
},
@@ -227,6 +233,12 @@
{
"name": "elementCreate"
},
{
"name": "enterDI"
},
{
"name": "enterView"
},
{
"name": "executeCheckHooks"
},
@@ -479,6 +491,15 @@
{
"name": "isStylingValueDefined"
},
{
"name": "leaveDI"
},
{
"name": "leaveView"
},
{
"name": "leaveViewProcessExit"
},
{
"name": "locateHostElement"
},
@@ -488,9 +509,6 @@
{
"name": "matchTemplateAttribute"
},
{
"name": "namespaceHTMLInternal"
},
{
"name": "nativeAppendChild"
},
@@ -560,9 +578,6 @@
{
"name": "renderView"
},
{
"name": "resetComponentState"
},
{
"name": "resetPreOrderHookFlags"
},
@@ -581,9 +596,6 @@
{
"name": "selectIndexInternal"
},
{
"name": "selectView"
},
{
"name": "setActiveHostElement"
},
@@ -599,9 +611,6 @@
{
"name": "setCurrentQueryIndex"
},
{
"name": "setCurrentStyleSanitizer"
},
{
"name": "setDirectiveStylingInput"
},
@@ -635,9 +644,6 @@
{
"name": "setStyle"
},
{
"name": "setTNodeAndViewData"
},
{
"name": "setUpAttributes"
},
@@ -134,6 +134,9 @@
{
"name": "addToViewTree"
},
{
"name": "allocLFrame"
},
{
"name": "appendChild"
},
@@ -152,6 +155,9 @@
{
"name": "callHooks"
},
{
"name": "createLFrame"
},
{
"name": "createLView"
},
@@ -188,6 +194,12 @@
{
"name": "domRendererFactory3"
},
{
"name": "enterDI"
},
{
"name": "enterView"
},
{
"name": "executeCheckHooks"
},
@@ -350,15 +362,21 @@
{
"name": "isRootView"
},
{
"name": "leaveDI"
},
{
"name": "leaveView"
},
{
"name": "leaveViewProcessExit"
},
{
"name": "locateHostElement"
},
{
"name": "markAsComponentHost"
},
{
"name": "namespaceHTMLInternal"
},
{
"name": "nativeAppendChild"
},
@@ -410,18 +428,12 @@
{
"name": "renderView"
},
{
"name": "resetComponentState"
},
{
"name": "resetPreOrderHookFlags"
},
{
"name": "selectIndexInternal"
},
{
"name": "selectView"
},
{
"name": "setActiveHostElement"
},
@@ -434,9 +446,6 @@
{
"name": "setCurrentQueryIndex"
},
{
"name": "setCurrentStyleSanitizer"
},
{
"name": "setHostBindings"
},
@@ -455,9 +464,6 @@
{
"name": "setSelectedIndex"
},
{
"name": "setTNodeAndViewData"
},
{
"name": "stringifyForError"
},
@@ -362,6 +362,9 @@
{
"name": "addToViewTree"
},
{
"name": "allocLFrame"
},
{
"name": "allocStylingMapArray"
},
@@ -461,6 +464,9 @@
{
"name": "createLContext"
},
{
"name": "createLFrame"
},
{
"name": "createLView"
},
@@ -527,6 +533,12 @@
{
"name": "elementPropertyInternal"
},
{
"name": "enterDI"
},
{
"name": "enterView"
},
{
"name": "executeCheckHooks"
},
@@ -977,6 +989,15 @@
{
"name": "iterateListLike"
},
{
"name": "leaveDI"
},
{
"name": "leaveView"
},
{
"name": "leaveViewProcessExit"
},
{
"name": "listenerInternal"
},
@@ -1022,9 +1043,6 @@
{
"name": "matchTemplateAttribute"
},
{
"name": "namespaceHTMLInternal"
},
{
"name": "nativeAppendChild"
},
@@ -1139,9 +1157,6 @@
{
"name": "renderView"
},
{
"name": "resetComponentState"
},
{
"name": "resetCurrentStyleSanitizer"
},
@@ -1175,9 +1190,6 @@
{
"name": "selectIndexInternal"
},
{
"name": "selectView"
},
{
"name": "setActiveElementFlag"
},
@@ -1247,9 +1259,6 @@
{
"name": "setStyle"
},
{
"name": "setTNodeAndViewData"
},
{
"name": "setUpAttributes"
},
+3 -3
View File
@@ -17,7 +17,7 @@ import {TNODE} from '../../src/render3/interfaces/injector';
import {TNodeType} from '../../src/render3/interfaces/node';
import {isProceduralRenderer} from '../../src/render3/interfaces/renderer';
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 {ComponentFixture, createComponent, createDirective} from './render_util';
@@ -225,7 +225,7 @@ describe('di', () => {
const contentView = createLView(
null, createTView(-1, null, 1, 0, null, null, null, null, null), null,
LViewFlags.CheckAlways, null, null, {} as any, {} as any);
const oldView = selectView(contentView, null);
enterView(contentView, null);
try {
const parentTNode =
getOrCreateTNode(contentView[TVIEW], null, 0, TNodeType.Element, null, null);
@@ -237,7 +237,7 @@ describe('di', () => {
const injector = getOrCreateNodeInjectorForNode(parentTNode, contentView);
expect(injector).not.toEqual(-1);
} finally {
selectView(oldView, null);
leaveViewProcessExit();
}
});
});
@@ -9,7 +9,6 @@ import {ɵɵdefineDirective, ɵɵelementEnd, ɵɵelementStart, ɵɵtext} from '.
import {createTNode, createTView} from '../../../../src/render3/instructions/shared';
import {RenderFlags} from '../../../../src/render3/interfaces/definition';
import {TNodeType, TViewNode} from '../../../../src/render3/interfaces/node';
import {resetComponentState} from '../../../../src/render3/state';
import {createBenchmark} from '../micro_bench';
import {createAndRenderLView} from '../setup';
@@ -78,9 +77,6 @@ const embeddedTView = createTView(
-1, testTemplate, 21, 10, [Tooltip.ɵdir], null, null, null,
[['position', 'top', 3, 'tooltip']]);
// initialize global state
resetComponentState();
// create view once so we don't profile first template pass
createAndRenderLView(null, embeddedTView, viewTNode);
@@ -10,7 +10,6 @@ import {createTNode, createTView} from '../../../../src/render3/instructions/sha
import {ɵɵtext} from '../../../../src/render3/instructions/text';
import {RenderFlags} from '../../../../src/render3/interfaces/definition';
import {TNodeType, TViewNode} from '../../../../src/render3/interfaces/node';
import {resetComponentState} from '../../../../src/render3/state';
import {createBenchmark} from '../micro_bench';
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']
]);
// initialize global state
resetComponentState();
// create view once so we don't profile first template pass
createAndRenderLView(null, embeddedTView, viewTNode);
@@ -10,7 +10,6 @@ import {ɵɵlistener} from '../../../../src/render3/instructions/listener';
import {createTNode, createTView} from '../../../../src/render3/instructions/shared';
import {RenderFlags} from '../../../../src/render3/interfaces/definition';
import {TNodeType, TViewNode} from '../../../../src/render3/interfaces/node';
import {resetComponentState} from '../../../../src/render3/state';
import {createBenchmark} from '../micro_bench';
import {createAndRenderLView} from '../setup';
@@ -79,9 +78,6 @@ const viewTNode = createTNode(null !, null, TNodeType.View, -1, null, null) as T
const embeddedTView =
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
createAndRenderLView(null, embeddedTView, viewTNode);
@@ -18,7 +18,7 @@ const noopChangeDetection = createBenchmark('noop change detection');
const refreshTime = noopChangeDetection('refresh');
// run change detection in the update mode
console.profile('noop_refresh');
console.profile('noop_change_detection');
while (refreshTime()) {
refreshView(rootLView, rootTView, null, null);
}
+3 -4
View File
@@ -14,7 +14,7 @@ import {ViewContainerRef} from '@angular/core/src/linker/view_container_ref';
import {Renderer2} from '@angular/core/src/render/api';
import {createLView, createTView, getOrCreateTNode, getOrCreateTView, renderComponentOrTemplate} from '@angular/core/src/render3/instructions/shared';
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 {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 {PlayerHandler} from '../../src/render3/interfaces/player';
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 {getRootView} from '../../src/render3/util/view_traversal_utils';
import {Sanitizer} from '../../src/sanitization/sanitizer';
@@ -251,7 +251,6 @@ export function renderTemplate<T>(
directives?: DirectiveDefListOrFactory | null, pipes?: PipeDefListOrFactory | null,
sanitizer?: Sanitizer | null, consts?: TAttributes[]): LView {
if (componentView === null) {
resetComponentState();
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
@@ -259,7 +258,7 @@ export function renderTemplate<T>(
const hostLView = createLView(
null, tView, {}, LViewFlags.CheckAlways | LViewFlags.IsRoot, null, null,
providedRendererFactory, renderer);
selectView(hostLView, null); // SUSPECT! why do we need to enter the View?
enterView(hostLView, null);
const def: ComponentDef<any> = ɵɵdefineComponent({
selectors: [],
@@ -8,8 +8,8 @@
*/
import {SECURITY_SCHEMA} from '@angular/compiler/src/schema/dom_security_schema';
import {HEADER_OFFSET, LView} from '@angular/core/src/render3/interfaces/view';
import {setTNodeAndViewData} from '@angular/core/src/render3/state';
import {LView} from '@angular/core/src/render3/interfaces/view';
import {enterView, leaveView} from '@angular/core/src/render3/state';
import {bypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript, bypassSanitizationTrustStyle, bypassSanitizationTrustUrl} from '../../src/sanitization/bypass';
import {getUrlSanitizer, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl, ɵɵsanitizeUrlOrResourceUrl} from '../../src/sanitization/sanitization';
@@ -20,8 +20,8 @@ function fakeLView(): LView {
}
describe('sanitization', () => {
beforeEach(() => setTNodeAndViewData(null !, fakeLView()));
afterEach(() => setTNodeAndViewData(null !, null !));
beforeEach(() => enterView(fakeLView(), null));
afterEach(() => leaveView());
class Wrap {
constructor(private value: string) {}
toString() { return this.value; }