refactor(ivy): move all of the instruction state into a singe object (#33093)
Turns out that writing to global state is more expensive than writing to a property on an object. Slower: ```` let count = 0; function increment() { count++; } ``` Faster: ```` const state = { count: 0 }; function increment() { state.count++; } ``` This change moves all of the instruction state into a single state object. `noop_change_detection` benchmark Pre refactoring: 16.7 us Post refactoring: 14.523 us (-13.3%) PR Close #33093
This commit is contained in:
parent
43487f6761
commit
bb53b6549c
|
@ -12,7 +12,7 @@
|
||||||
"master": {
|
"master": {
|
||||||
"uncompressed": {
|
"uncompressed": {
|
||||||
"runtime": 1440,
|
"runtime": 1440,
|
||||||
"main": 13415,
|
"main": 14228,
|
||||||
"polyfills": 45340
|
"polyfills": 45340
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
"master": {
|
"master": {
|
||||||
"uncompressed": {
|
"uncompressed": {
|
||||||
"runtime": 1440,
|
"runtime": 1440,
|
||||||
"main": 123904,
|
"main": 125674,
|
||||||
"polyfills": 45340
|
"polyfills": 45340
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,7 +184,7 @@ function stylingProp(
|
||||||
// it's important we remove the current style sanitizer once the
|
// it's important we remove the current style sanitizer once the
|
||||||
// element exits, otherwise it will be used by the next styling
|
// element exits, otherwise it will be used by the next styling
|
||||||
// instructions for the next element.
|
// instructions for the next element.
|
||||||
setElementExitFn(resetCurrentStyleSanitizer);
|
setElementExitFn(stylingApply);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Context Resolution (or first update) Case: save the value
|
// Context Resolution (or first update) Case: save the value
|
||||||
|
@ -354,7 +354,7 @@ function _stylingMap(
|
||||||
// it's important we remove the current style sanitizer once the
|
// it's important we remove the current style sanitizer once the
|
||||||
// element exits, otherwise it will be used by the next styling
|
// element exits, otherwise it will be used by the next styling
|
||||||
// instructions for the next element.
|
// instructions for the next element.
|
||||||
setElementExitFn(resetCurrentStyleSanitizer);
|
setElementExitFn(stylingApply);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
updated = valueHasChanged;
|
updated = valueHasChanged;
|
||||||
|
|
|
@ -7,67 +7,185 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {StyleSanitizeFn} from '../sanitization/style_sanitizer';
|
import {StyleSanitizeFn} from '../sanitization/style_sanitizer';
|
||||||
import {assertDefined} from '../util/assert';
|
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 {TElementNode, TNode, TViewNode} from './interfaces/node';
|
||||||
import {CONTEXT, DECLARATION_VIEW, LView, OpaqueViewState} from './interfaces/view';
|
import {CONTEXT, DECLARATION_VIEW, LView, OpaqueViewState} from './interfaces/view';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store the element depth count. This is used to identify the root elements of the template
|
* All implicit instruction state is stored here.
|
||||||
* so that we can than attach `LView` to only those elements.
|
*
|
||||||
|
* 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.
|
||||||
*/
|
*/
|
||||||
let elementDepthCount !: number;
|
interface InstructionState {
|
||||||
|
/**
|
||||||
|
* State of the current view being processed.
|
||||||
|
*
|
||||||
|
* An array of nodes (text, element, container, etc), pipes, their bindings, and
|
||||||
|
* any local variables that need to be stored between invocations.
|
||||||
|
*/
|
||||||
|
lView: LView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to set the parent property when nodes are created and track query results.
|
||||||
|
*
|
||||||
|
* This is used in conjection with `isParent`.
|
||||||
|
*/
|
||||||
|
previousOrParentTNode: TNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If `isParent` is:
|
||||||
|
* - `true`: then `previousOrParentTNode` points to a parent node.
|
||||||
|
* - `false`: then `previousOrParentTNode` points to previous node (sibling).
|
||||||
|
*/
|
||||||
|
isParent: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Index of currently selected element in LView.
|
||||||
|
*
|
||||||
|
* Used by binding instructions. Updated as part of advance instruction.
|
||||||
|
*/
|
||||||
|
selectedIndex: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The last viewData retrieved by nextContext().
|
||||||
|
* Allows building nextContext() and reference() calls.
|
||||||
|
*
|
||||||
|
* e.g. const inner = x().$implicit; const outer = x().$implicit;
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
* so that we can then attach `LView` to only those elements.
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
currentNamespace: string|null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current sanitizer
|
||||||
|
*/
|
||||||
|
currentSanitizer: StyleSanitizeFn|null;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used when processing host bindings.
|
||||||
|
*/
|
||||||
|
currentDirectiveDef: DirectiveDef<any>|ComponentDef<any>|null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used as the starting directive id value.
|
||||||
|
*
|
||||||
|
* All subsequent directives are incremented from this value onwards.
|
||||||
|
* The reason why this value is `1` instead of `0` is because the `0`
|
||||||
|
* value is reserved for the template.
|
||||||
|
*/
|
||||||
|
activeDirectiveId: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The root index from which pure function instructions should calculate their binding
|
||||||
|
* indices. In component views, this is TView.bindingStartIndex. In a host binding
|
||||||
|
* context, this is the TView.expandoStartIndex + any dirs/hostVars before the given dir.
|
||||||
|
*/
|
||||||
|
bindingRootIndex: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current index of a View or Content Query which needs to be processed next.
|
||||||
|
* We iterate over the list of Queries and increment current query index at every step.
|
||||||
|
*/
|
||||||
|
currentQueryIndex: number;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to be called when the element is exited.
|
||||||
|
*
|
||||||
|
* NOTE: The function is here for tree shakable purposes since it is only needed by styling.
|
||||||
|
*/
|
||||||
|
elementExitFn: (() => void)|null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const instructionState: InstructionState = {
|
||||||
|
previousOrParentTNode: 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,
|
||||||
|
currentNamespace: null,
|
||||||
|
currentSanitizer: null,
|
||||||
|
currentDirectiveDef: null,
|
||||||
|
activeDirectiveId: 0,
|
||||||
|
bindingRootIndex: -1,
|
||||||
|
currentQueryIndex: 0,
|
||||||
|
elementExitFn: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export function getElementDepthCount() {
|
export function getElementDepthCount() {
|
||||||
// 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)
|
||||||
return elementDepthCount;
|
return instructionState.elementDepthCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function increaseElementDepthCount() {
|
export function increaseElementDepthCount() {
|
||||||
elementDepthCount++;
|
instructionState.elementDepthCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function decreaseElementDepthCount() {
|
export function decreaseElementDepthCount() {
|
||||||
elementDepthCount--;
|
instructionState.elementDepthCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
let currentDirectiveDef: DirectiveDef<any>|ComponentDef<any>|null = null;
|
|
||||||
|
|
||||||
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)
|
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
|
||||||
return currentDirectiveDef;
|
return instructionState.currentDirectiveDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setCurrentDirectiveDef(def: DirectiveDef<any>| ComponentDef<any>| null): void {
|
export function setCurrentDirectiveDef(def: DirectiveDef<any>| ComponentDef<any>| null): void {
|
||||||
currentDirectiveDef = def;
|
instructionState.currentDirectiveDef = def;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores whether directives should be matched to elements.
|
|
||||||
*
|
|
||||||
* When template contains `ngNonBindable` than 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>
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
let bindingsEnabled !: boolean;
|
|
||||||
|
|
||||||
export function getBindingsEnabled(): boolean {
|
export function getBindingsEnabled(): boolean {
|
||||||
// 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)
|
||||||
return bindingsEnabled;
|
return instructionState.bindingsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,7 +209,7 @@ export function getBindingsEnabled(): boolean {
|
||||||
* @codeGenApi
|
* @codeGenApi
|
||||||
*/
|
*/
|
||||||
export function ɵɵenableBindings(): void {
|
export function ɵɵenableBindings(): void {
|
||||||
bindingsEnabled = true;
|
instructionState.bindingsEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -114,22 +232,13 @@ export function ɵɵenableBindings(): void {
|
||||||
* @codeGenApi
|
* @codeGenApi
|
||||||
*/
|
*/
|
||||||
export function ɵɵdisableBindings(): void {
|
export function ɵɵdisableBindings(): void {
|
||||||
bindingsEnabled = false;
|
instructionState.bindingsEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLView(): LView {
|
export function getLView(): LView {
|
||||||
return lView;
|
return instructionState.lView;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Used as the starting directive id value.
|
|
||||||
*
|
|
||||||
* All subsequent directives are incremented from this value onwards.
|
|
||||||
* The reason why this value is `1` instead of `0` is because the `0`
|
|
||||||
* value is reserved for the template.
|
|
||||||
*/
|
|
||||||
let activeDirectiveId = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flags used for an active element during change detection.
|
* Flags used for an active element during change detection.
|
||||||
*
|
*
|
||||||
|
@ -150,14 +259,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 (_selectedIndex & flag) === flag;
|
return (instructionState.selectedIndex & flag) === flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a flag is for the active element.
|
* Sets a flag is for the active element.
|
||||||
*/
|
*/
|
||||||
export function setActiveElementFlag(flag: ActiveElementFlags) {
|
export function setActiveElementFlag(flag: ActiveElementFlags) {
|
||||||
_selectedIndex |= flag;
|
instructionState.selectedIndex |= flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -173,16 +282,15 @@ export function setActiveHostElement(elementIndex: number | null = null) {
|
||||||
executeElementExitFn();
|
executeElementExitFn();
|
||||||
}
|
}
|
||||||
setSelectedIndex(elementIndex === null ? -1 : elementIndex);
|
setSelectedIndex(elementIndex === null ? -1 : elementIndex);
|
||||||
activeDirectiveId = 0;
|
instructionState.activeDirectiveId = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _elementExitFn: Function|null = null;
|
|
||||||
export function executeElementExitFn() {
|
export function executeElementExitFn() {
|
||||||
_elementExitFn !();
|
instructionState.elementExitFn !();
|
||||||
// TODO (matsko|misko): remove this unassignment once the state management of
|
// TODO (matsko|misko): remove this unassignment once the state management of
|
||||||
// global variables are better managed.
|
// global variables are better managed.
|
||||||
_selectedIndex &= ~ActiveElementFlags.RunExitFn;
|
instructionState.selectedIndex &= ~ActiveElementFlags.RunExitFn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -198,9 +306,13 @@ export function executeElementExitFn() {
|
||||||
*
|
*
|
||||||
* @param fn
|
* @param fn
|
||||||
*/
|
*/
|
||||||
export function setElementExitFn(fn: Function): void {
|
export function setElementExitFn(fn: () => void): void {
|
||||||
setActiveElementFlag(ActiveElementFlags.RunExitFn);
|
setActiveElementFlag(ActiveElementFlags.RunExitFn);
|
||||||
_elementExitFn = fn;
|
if (instructionState.elementExitFn == null) {
|
||||||
|
instructionState.elementExitFn = fn;
|
||||||
|
}
|
||||||
|
ngDevMode &&
|
||||||
|
assertEqual(instructionState.elementExitFn, fn, 'Expecting to always get the same function');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -219,7 +331,7 @@ export function setElementExitFn(fn: Function): void {
|
||||||
* different set of directives).
|
* different set of directives).
|
||||||
*/
|
*/
|
||||||
export function getActiveDirectiveId() {
|
export function getActiveDirectiveId() {
|
||||||
return activeDirectiveId;
|
return instructionState.activeDirectiveId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -248,7 +360,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.
|
||||||
activeDirectiveId += 1;
|
instructionState.activeDirectiveId += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -263,113 +375,67 @@ export function incrementActiveDirectiveId() {
|
||||||
* @codeGenApi
|
* @codeGenApi
|
||||||
*/
|
*/
|
||||||
export function ɵɵrestoreView(viewToRestore: OpaqueViewState) {
|
export function ɵɵrestoreView(viewToRestore: OpaqueViewState) {
|
||||||
contextLView = viewToRestore as any as LView;
|
instructionState.contextLView = viewToRestore as any as LView;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Used to set the parent property when nodes are created and track query results. */
|
|
||||||
let previousOrParentTNode: TNode;
|
|
||||||
|
|
||||||
export function getPreviousOrParentTNode(): TNode {
|
export function getPreviousOrParentTNode(): TNode {
|
||||||
// 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)
|
||||||
return previousOrParentTNode;
|
return instructionState.previousOrParentTNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setPreviousOrParentTNode(tNode: TNode, _isParent: boolean) {
|
export function setPreviousOrParentTNode(tNode: TNode, _isParent: boolean) {
|
||||||
previousOrParentTNode = tNode;
|
instructionState.previousOrParentTNode = tNode;
|
||||||
isParent = _isParent;
|
instructionState.isParent = _isParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setTNodeAndViewData(tNode: TNode, view: LView) {
|
export function setTNodeAndViewData(tNode: TNode, view: LView) {
|
||||||
ngDevMode && assertLViewOrUndefined(view);
|
ngDevMode && assertLViewOrUndefined(view);
|
||||||
previousOrParentTNode = tNode;
|
instructionState.previousOrParentTNode = tNode;
|
||||||
lView = view;
|
instructionState.lView = view;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* If `isParent` is:
|
|
||||||
* - `true`: then `previousOrParentTNode` points to a parent node.
|
|
||||||
* - `false`: then `previousOrParentTNode` points to previous node (sibling).
|
|
||||||
*/
|
|
||||||
let isParent: boolean;
|
|
||||||
|
|
||||||
export function getIsParent(): boolean {
|
export function getIsParent(): boolean {
|
||||||
// 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)
|
||||||
return isParent;
|
return instructionState.isParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setIsNotParent(): void {
|
export function setIsNotParent(): void {
|
||||||
isParent = false;
|
instructionState.isParent = false;
|
||||||
}
|
}
|
||||||
export function setIsParent(): void {
|
export function setIsParent(): void {
|
||||||
isParent = true;
|
instructionState.isParent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* State of the current view being processed.
|
|
||||||
*
|
|
||||||
* An array of nodes (text, element, container, etc), pipes, their bindings, and
|
|
||||||
* any local variables that need to be stored between invocations.
|
|
||||||
*/
|
|
||||||
let lView: LView;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The last viewData retrieved by nextContext().
|
|
||||||
* Allows building nextContext() and reference() calls.
|
|
||||||
*
|
|
||||||
* e.g. const inner = x().$implicit; const outer = x().$implicit;
|
|
||||||
*/
|
|
||||||
let contextLView: LView = null !;
|
|
||||||
|
|
||||||
export function getContextLView(): LView {
|
export function getContextLView(): LView {
|
||||||
// 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)
|
||||||
return contextLView;
|
return instructionState.contextLView;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* In this mode, any changes in bindings will throw an ExpressionChangedAfterChecked error.
|
|
||||||
*
|
|
||||||
* Necessary to support ChangeDetectorRef.checkNoChanges().
|
|
||||||
*/
|
|
||||||
let checkNoChangesMode = false;
|
|
||||||
|
|
||||||
export function getCheckNoChangesMode(): boolean {
|
export function getCheckNoChangesMode(): boolean {
|
||||||
// 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)
|
||||||
return checkNoChangesMode;
|
return instructionState.checkNoChangesMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setCheckNoChangesMode(mode: boolean): void {
|
export function setCheckNoChangesMode(mode: boolean): void {
|
||||||
checkNoChangesMode = mode;
|
instructionState.checkNoChangesMode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The root index from which pure function instructions should calculate their binding
|
|
||||||
* indices. In component views, this is TView.bindingStartIndex. In a host binding
|
|
||||||
* context, this is the TView.expandoStartIndex + any dirs/hostVars before the given dir.
|
|
||||||
*/
|
|
||||||
let bindingRootIndex: number = -1;
|
|
||||||
|
|
||||||
// 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 bindingRootIndex;
|
return instructionState.bindingRootIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setBindingRoot(value: number) {
|
export function setBindingRoot(value: number) {
|
||||||
bindingRootIndex = value;
|
instructionState.bindingRootIndex = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Current index of a View or Content Query which needs to be processed next.
|
|
||||||
* We iterate over the list of Queries and increment current query index at every step.
|
|
||||||
*/
|
|
||||||
let currentQueryIndex: number = 0;
|
|
||||||
|
|
||||||
export function getCurrentQueryIndex(): number {
|
export function getCurrentQueryIndex(): number {
|
||||||
// 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)
|
||||||
return currentQueryIndex;
|
return instructionState.currentQueryIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setCurrentQueryIndex(value: number): void {
|
export function setCurrentQueryIndex(value: number): void {
|
||||||
currentQueryIndex = value;
|
instructionState.currentQueryIndex = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -390,18 +456,18 @@ export function selectView(newView: LView, hostTNode: TElementNode | TViewNode |
|
||||||
}
|
}
|
||||||
|
|
||||||
ngDevMode && assertLViewOrUndefined(newView);
|
ngDevMode && assertLViewOrUndefined(newView);
|
||||||
const oldView = lView;
|
const oldView = instructionState.lView;
|
||||||
|
|
||||||
previousOrParentTNode = hostTNode !;
|
instructionState.previousOrParentTNode = hostTNode !;
|
||||||
isParent = true;
|
instructionState.isParent = true;
|
||||||
|
|
||||||
lView = contextLView = newView;
|
instructionState.lView = instructionState.contextLView = newView;
|
||||||
return oldView;
|
return oldView;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function nextContextImpl<T = any>(level: number = 1): T {
|
export function nextContextImpl<T = any>(level: number = 1): T {
|
||||||
contextLView = walkUpViews(level, contextLView !);
|
instructionState.contextLView = walkUpViews(level, instructionState.contextLView !);
|
||||||
return contextLView[CONTEXT] as T;
|
return instructionState.contextLView[CONTEXT] as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
function walkUpViews(nestingLevel: number, currentView: LView): LView {
|
function walkUpViews(nestingLevel: number, currentView: LView): LView {
|
||||||
|
@ -419,16 +485,13 @@ function walkUpViews(nestingLevel: number, currentView: LView): LView {
|
||||||
* Resets the application state.
|
* Resets the application state.
|
||||||
*/
|
*/
|
||||||
export function resetComponentState() {
|
export function resetComponentState() {
|
||||||
isParent = false;
|
instructionState.isParent = false;
|
||||||
previousOrParentTNode = null !;
|
instructionState.previousOrParentTNode = null !;
|
||||||
elementDepthCount = 0;
|
instructionState.elementDepthCount = 0;
|
||||||
bindingsEnabled = true;
|
instructionState.bindingsEnabled = true;
|
||||||
setCurrentStyleSanitizer(null);
|
setCurrentStyleSanitizer(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* tslint:disable */
|
|
||||||
let _selectedIndex = -1 << ActiveElementFlags.Size;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the most recent index passed to {@link select}
|
* Gets the most recent index passed to {@link select}
|
||||||
*
|
*
|
||||||
|
@ -436,7 +499,7 @@ let _selectedIndex = -1 << ActiveElementFlags.Size;
|
||||||
* current `LView` to act on.
|
* current `LView` to act on.
|
||||||
*/
|
*/
|
||||||
export function getSelectedIndex() {
|
export function getSelectedIndex() {
|
||||||
return _selectedIndex >> ActiveElementFlags.Size;
|
return instructionState.selectedIndex >> ActiveElementFlags.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -449,19 +512,17 @@ 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) {
|
||||||
_selectedIndex = index << ActiveElementFlags.Size;
|
instructionState.selectedIndex = index << ActiveElementFlags.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let _currentNamespace: string|null = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the namespace used to create elements to `'http://www.w3.org/2000/svg'` in global state.
|
* Sets the namespace used to create elements to `'http://www.w3.org/2000/svg'` in global state.
|
||||||
*
|
*
|
||||||
* @codeGenApi
|
* @codeGenApi
|
||||||
*/
|
*/
|
||||||
export function ɵɵnamespaceSVG() {
|
export function ɵɵnamespaceSVG() {
|
||||||
_currentNamespace = 'http://www.w3.org/2000/svg';
|
instructionState.currentNamespace = 'http://www.w3.org/2000/svg';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -470,7 +531,7 @@ export function ɵɵnamespaceSVG() {
|
||||||
* @codeGenApi
|
* @codeGenApi
|
||||||
*/
|
*/
|
||||||
export function ɵɵnamespaceMathML() {
|
export function ɵɵnamespaceMathML() {
|
||||||
_currentNamespace = 'http://www.w3.org/1998/MathML/';
|
instructionState.currentNamespace = 'http://www.w3.org/1998/MathML/';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -488,16 +549,15 @@ export function ɵɵnamespaceHTML() {
|
||||||
* `createElement` rather than `createElementNS`.
|
* `createElement` rather than `createElementNS`.
|
||||||
*/
|
*/
|
||||||
export function namespaceHTMLInternal() {
|
export function namespaceHTMLInternal() {
|
||||||
_currentNamespace = null;
|
instructionState.currentNamespace = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNamespace(): string|null {
|
export function getNamespace(): string|null {
|
||||||
return _currentNamespace;
|
return instructionState.currentNamespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
let _currentSanitizer: StyleSanitizeFn|null;
|
|
||||||
export function setCurrentStyleSanitizer(sanitizer: StyleSanitizeFn | null) {
|
export function setCurrentStyleSanitizer(sanitizer: StyleSanitizeFn | null) {
|
||||||
_currentSanitizer = sanitizer;
|
instructionState.currentSanitizer = sanitizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resetCurrentStyleSanitizer() {
|
export function resetCurrentStyleSanitizer() {
|
||||||
|
@ -505,5 +565,5 @@ export function resetCurrentStyleSanitizer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCurrentStyleSanitizer() {
|
export function getCurrentStyleSanitizer() {
|
||||||
return _currentSanitizer;
|
return instructionState.currentSanitizer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,21 +140,12 @@
|
||||||
{
|
{
|
||||||
"name": "__window"
|
"name": "__window"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "_currentNamespace"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "_elementExitFn"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "_global"
|
"name": "_global"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "_renderCompCount"
|
"name": "_renderCompCount"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "_selectedIndex"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "addComponentLogic"
|
"name": "addComponentLogic"
|
||||||
},
|
},
|
||||||
|
@ -188,9 +179,6 @@
|
||||||
{
|
{
|
||||||
"name": "callHooks"
|
"name": "callHooks"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "checkNoChangesMode"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "concatString"
|
"name": "concatString"
|
||||||
},
|
},
|
||||||
|
@ -431,6 +419,9 @@
|
||||||
{
|
{
|
||||||
"name": "instantiateRootComponent"
|
"name": "instantiateRootComponent"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "instructionState"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "invertObject"
|
"name": "invertObject"
|
||||||
},
|
},
|
||||||
|
|
|
@ -125,18 +125,12 @@
|
||||||
{
|
{
|
||||||
"name": "__window"
|
"name": "__window"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "_elementExitFn"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "_global"
|
"name": "_global"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "_renderCompCount"
|
"name": "_renderCompCount"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "_selectedIndex"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "addToViewTree"
|
"name": "addToViewTree"
|
||||||
},
|
},
|
||||||
|
@ -158,9 +152,6 @@
|
||||||
{
|
{
|
||||||
"name": "callHooks"
|
"name": "callHooks"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "checkNoChangesMode"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "createLView"
|
"name": "createLView"
|
||||||
},
|
},
|
||||||
|
@ -332,6 +323,9 @@
|
||||||
{
|
{
|
||||||
"name": "instantiateRootComponent"
|
"name": "instantiateRootComponent"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "instructionState"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "invertObject"
|
"name": "invertObject"
|
||||||
},
|
},
|
||||||
|
|
|
@ -326,33 +326,21 @@
|
||||||
{
|
{
|
||||||
"name": "_currentInjector"
|
"name": "_currentInjector"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "_currentNamespace"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "_devMode"
|
"name": "_devMode"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "_elementExitFn"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "_global"
|
"name": "_global"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "_renderCompCount"
|
"name": "_renderCompCount"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "_selectedIndex"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "_state"
|
"name": "_state"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "_symbolIterator"
|
"name": "_symbolIterator"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "activeDirectiveId"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "addBindingIntoContext"
|
"name": "addBindingIntoContext"
|
||||||
},
|
},
|
||||||
|
@ -446,9 +434,6 @@
|
||||||
{
|
{
|
||||||
"name": "checkNoChangesInternal"
|
"name": "checkNoChangesInternal"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "checkNoChangesMode"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "cleanUpView"
|
"name": "cleanUpView"
|
||||||
},
|
},
|
||||||
|
@ -461,9 +446,6 @@
|
||||||
{
|
{
|
||||||
"name": "containerInternal"
|
"name": "containerInternal"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "contextLView"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "createContainerRef"
|
"name": "createContainerRef"
|
||||||
},
|
},
|
||||||
|
@ -899,6 +881,9 @@
|
||||||
{
|
{
|
||||||
"name": "instantiateRootComponent"
|
"name": "instantiateRootComponent"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "instructionState"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "interpolation1"
|
"name": "interpolation1"
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue