feat(ivy): in `ngDevMode` use named object literals and arrays for easier debugging/profiling (#30542)
PR Close #30542
This commit is contained in:
parent
c7850fff3b
commit
55a14e4866
|
@ -6,31 +6,31 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getPluralCase } from '../i18n/localization';
|
|
||||||
import { getTemplateContent, SRCSET_ATTRS, URI_ATTRS, VALID_ATTRS, VALID_ELEMENTS } from '../sanitization/html_sanitizer';
|
|
||||||
import { InertBodyHelper } from '../sanitization/inert_body';
|
|
||||||
import { sanitizeSrcset, _sanitizeUrl } from '../sanitization/url_sanitizer';
|
|
||||||
import { addAllToArray } from '../util/array_utils';
|
|
||||||
import { assertDataInRange, assertDefined, assertEqual, assertGreaterThan } from '../util/assert';
|
|
||||||
import '../util/ng_i18n_closure_mode';
|
import '../util/ng_i18n_closure_mode';
|
||||||
import { attachPatchData } from './context_discovery';
|
|
||||||
import { attachI18nOpCodesDebug } from './debug';
|
|
||||||
import { elementAttributeInternal, ɵɵload, ɵɵtextBinding } from './instructions/all';
|
|
||||||
import { allocExpando, elementPropertyInternal, getOrCreateTNode, setInputsForProperty } from './instructions/shared';
|
|
||||||
import { LContainer, NATIVE } from './interfaces/container';
|
|
||||||
import { COMMENT_MARKER, ELEMENT_MARKER, I18nMutateOpCode, I18nMutateOpCodes, I18nUpdateOpCode, I18nUpdateOpCodes, IcuType, TI18n, TIcu } from './interfaces/i18n';
|
|
||||||
import { TElementNode, TIcuContainerNode, TNode, TNodeType } from './interfaces/node';
|
|
||||||
import { RComment, RElement, RText } from './interfaces/renderer';
|
|
||||||
import { SanitizerFn } from './interfaces/sanitization';
|
|
||||||
import { StylingContext } from './interfaces/styling';
|
|
||||||
import { BINDING_INDEX, HEADER_OFFSET, LView, RENDERER, TVIEW, TView, T_HOST } from './interfaces/view';
|
|
||||||
import { appendChild, createTextNode, nativeRemoveNode } from './node_manipulation';
|
|
||||||
import { getIsParent, getLView, getPreviousOrParentTNode, setIsNotParent, setPreviousOrParentTNode } from './state';
|
|
||||||
import { NO_CHANGE } from './tokens';
|
|
||||||
import { renderStringify } from './util/misc_utils';
|
|
||||||
import { getNativeByIndex, getNativeByTNode, getTNode, isLContainer } from './util/view_utils';
|
|
||||||
|
|
||||||
|
import {getPluralCase} from '../i18n/localization';
|
||||||
|
import {SRCSET_ATTRS, URI_ATTRS, VALID_ATTRS, VALID_ELEMENTS, getTemplateContent} from '../sanitization/html_sanitizer';
|
||||||
|
import {InertBodyHelper} from '../sanitization/inert_body';
|
||||||
|
import {_sanitizeUrl, sanitizeSrcset} from '../sanitization/url_sanitizer';
|
||||||
|
import {addAllToArray} from '../util/array_utils';
|
||||||
|
import {assertDataInRange, assertDefined, assertEqual, assertGreaterThan} from '../util/assert';
|
||||||
|
|
||||||
|
import {attachPatchData} from './context_discovery';
|
||||||
|
import {elementAttributeInternal, ɵɵload, ɵɵtextBinding} from './instructions/all';
|
||||||
|
import {attachI18nOpCodesDebug} from './instructions/lview_debug';
|
||||||
|
import {allocExpando, elementPropertyInternal, getOrCreateTNode, setInputsForProperty} from './instructions/shared';
|
||||||
|
import {LContainer, NATIVE} from './interfaces/container';
|
||||||
|
import {COMMENT_MARKER, ELEMENT_MARKER, I18nMutateOpCode, I18nMutateOpCodes, I18nUpdateOpCode, I18nUpdateOpCodes, IcuType, TI18n, TIcu} from './interfaces/i18n';
|
||||||
|
import {TElementNode, TIcuContainerNode, TNode, TNodeType} from './interfaces/node';
|
||||||
|
import {RComment, RElement, RText} from './interfaces/renderer';
|
||||||
|
import {SanitizerFn} from './interfaces/sanitization';
|
||||||
|
import {StylingContext} from './interfaces/styling';
|
||||||
|
import {BINDING_INDEX, HEADER_OFFSET, LView, RENDERER, TVIEW, TView, T_HOST} from './interfaces/view';
|
||||||
|
import {appendChild, createTextNode, nativeRemoveNode} from './node_manipulation';
|
||||||
|
import {getIsParent, getLView, getPreviousOrParentTNode, setIsNotParent, setPreviousOrParentTNode} from './state';
|
||||||
|
import {NO_CHANGE} from './tokens';
|
||||||
|
import {renderStringify} from './util/misc_utils';
|
||||||
|
import {getNativeByIndex, getNativeByTNode, getTNode, isLContainer} from './util/view_utils';
|
||||||
|
|
||||||
|
|
||||||
const MARKER = `<EFBFBD>`;
|
const MARKER = `<EFBFBD>`;
|
||||||
|
|
|
@ -6,20 +6,24 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {ComponentTemplate} from '..';
|
||||||
|
import {SchemaMetadata} from '../../core';
|
||||||
import {assertDefined} from '../../util/assert';
|
import {assertDefined} from '../../util/assert';
|
||||||
|
import {createNamedArrayType} from '../../util/named_array_type';
|
||||||
import {ACTIVE_INDEX, CONTAINER_HEADER_OFFSET, LContainer, NATIVE} from '../interfaces/container';
|
import {ACTIVE_INDEX, CONTAINER_HEADER_OFFSET, LContainer, NATIVE} from '../interfaces/container';
|
||||||
|
import {DirectiveDefList, PipeDefList, ViewQueriesFunction} from '../interfaces/definition';
|
||||||
import {COMMENT_MARKER, ELEMENT_MARKER, I18nMutateOpCode, I18nMutateOpCodes, I18nUpdateOpCode, I18nUpdateOpCodes, TIcu} from '../interfaces/i18n';
|
import {COMMENT_MARKER, ELEMENT_MARKER, I18nMutateOpCode, I18nMutateOpCodes, I18nUpdateOpCode, I18nUpdateOpCodes, TIcu} from '../interfaces/i18n';
|
||||||
import {TNode} from '../interfaces/node';
|
import {TElementNode, TNode, TViewNode} from '../interfaces/node';
|
||||||
import {LQueries} from '../interfaces/query';
|
import {LQueries} from '../interfaces/query';
|
||||||
import {RComment, RElement} from '../interfaces/renderer';
|
import {RComment, RElement} from '../interfaces/renderer';
|
||||||
import {StylingContext} from '../interfaces/styling';
|
import {StylingContext} from '../interfaces/styling';
|
||||||
import {BINDING_INDEX, CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTENT_QUERIES, CONTEXT, DECLARATION_VIEW, FLAGS, HEADER_OFFSET, HOST, INJECTOR, LView, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, RENDERER_FACTORY, SANITIZER, TVIEW, T_HOST} from '../interfaces/view';
|
import {BINDING_INDEX, CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTENT_QUERIES, CONTEXT, DECLARATION_VIEW, ExpandoInstructions, FLAGS, HEADER_OFFSET, HOST, HookData, INJECTOR, LView, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, RENDERER_FACTORY, SANITIZER, TData, TVIEW, TView as ITView, T_HOST} from '../interfaces/view';
|
||||||
import {runtimeIsNewStylingInUse} from '../styling_next/state';
|
import {runtimeIsNewStylingInUse} from '../styling_next/state';
|
||||||
import {DebugStyling as DebugNewStyling, NodeStylingDebug} from '../styling_next/styling_debug';
|
import {DebugStyling as DebugNewStyling, NodeStylingDebug} from '../styling_next/styling_debug';
|
||||||
import {attachDebugObject} from '../util/debug_utils';
|
import {attachDebugObject} from '../util/debug_utils';
|
||||||
import {getTNode, isStylingContext, unwrapRNode} from '../util/view_utils';
|
import {getTNode, isStylingContext, unwrapRNode} from '../util/view_utils';
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file contains conditionally attached classes which provide human readable (debug) level
|
* This file contains conditionally attached classes which provide human readable (debug) level
|
||||||
* information for `LView`, `LContainer` and other internal data structures. These data structures
|
* information for `LView`, `LContainer` and other internal data structures. These data structures
|
||||||
|
@ -50,6 +54,80 @@ import {getTNode, isStylingContext, unwrapRNode} from '../util/view_utils';
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
export const LViewArray = ngDevMode && createNamedArrayType('LView');
|
||||||
|
let LVIEW_EMPTY: unknown[]; // can't initialize here or it will not be tree shaken, because `LView`
|
||||||
|
// constructor could have side-effects.
|
||||||
|
/**
|
||||||
|
* This function clones a blueprint and creates LView.
|
||||||
|
*
|
||||||
|
* Simple slice will keep the same type, and we need it to be LView
|
||||||
|
*/
|
||||||
|
export function cloneToLView(list: any[]): LView {
|
||||||
|
if (LVIEW_EMPTY === undefined) LVIEW_EMPTY = new LViewArray !();
|
||||||
|
return LVIEW_EMPTY.concat(list) as any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is a debug version of Object literal so that we can have constructor name show up in
|
||||||
|
* debug tools in ngDevMode.
|
||||||
|
*/
|
||||||
|
export const TViewConstructor = class TView implements ITView {
|
||||||
|
constructor(
|
||||||
|
public id: number, //
|
||||||
|
public blueprint: LView, //
|
||||||
|
public template: ComponentTemplate<{}>|null, //
|
||||||
|
public viewQuery: ViewQueriesFunction<{}>|null, //
|
||||||
|
public node: TViewNode|TElementNode|null, //
|
||||||
|
public data: TData, //
|
||||||
|
public bindingStartIndex: number, //
|
||||||
|
public viewQueryStartIndex: number, //
|
||||||
|
public expandoStartIndex: number, //
|
||||||
|
public expandoInstructions: ExpandoInstructions|null, //
|
||||||
|
public firstTemplatePass: boolean, //
|
||||||
|
public staticViewQueries: boolean, //
|
||||||
|
public staticContentQueries: boolean, //
|
||||||
|
public preOrderHooks: HookData|null, //
|
||||||
|
public preOrderCheckHooks: HookData|null, //
|
||||||
|
public contentHooks: HookData|null, //
|
||||||
|
public contentCheckHooks: HookData|null, //
|
||||||
|
public viewHooks: HookData|null, //
|
||||||
|
public viewCheckHooks: HookData|null, //
|
||||||
|
public destroyHooks: HookData|null, //
|
||||||
|
public cleanup: any[]|null, //
|
||||||
|
public contentQueries: number[]|null, //
|
||||||
|
public components: number[]|null, //
|
||||||
|
public directiveRegistry: DirectiveDefList|null, //
|
||||||
|
public pipeRegistry: PipeDefList|null, //
|
||||||
|
public firstChild: TNode|null, //
|
||||||
|
public schemas: SchemaMetadata[]|null, //
|
||||||
|
) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
const TViewData = ngDevMode && createNamedArrayType('TViewData');
|
||||||
|
let TVIEWDATA_EMPTY:
|
||||||
|
unknown[]; // can't initialize here or it will not be tree shaken, because `LView`
|
||||||
|
// constructor could have side-effects.
|
||||||
|
/**
|
||||||
|
* This function clones a blueprint and creates TData.
|
||||||
|
*
|
||||||
|
* Simple slice will keep the same type, and we need it to be TData
|
||||||
|
*/
|
||||||
|
export function cloneToTViewData(list: any[]): TData {
|
||||||
|
if (TVIEWDATA_EMPTY === undefined) TVIEWDATA_EMPTY = new TViewData !();
|
||||||
|
return TVIEWDATA_EMPTY.concat(list) as any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LViewBlueprint = ngDevMode && createNamedArrayType('LViewBlueprint');
|
||||||
|
export const MatchesArray = ngDevMode && createNamedArrayType('MatchesArray');
|
||||||
|
export const TViewComponents = ngDevMode && createNamedArrayType('TViewComponents');
|
||||||
|
export const TNodeLocalNames = ngDevMode && createNamedArrayType('TNodeLocalNames');
|
||||||
|
export const TNodeInitialInputs = ngDevMode && createNamedArrayType('TNodeInitialInputs');
|
||||||
|
export const TNodeInitialData = ngDevMode && createNamedArrayType('TNodeInitialData');
|
||||||
|
export const LCleanup = ngDevMode && createNamedArrayType('LCleanup');
|
||||||
|
export const TCleanup = ngDevMode && createNamedArrayType('TCleanup');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export function attachLViewDebug(lView: LView) {
|
export function attachLViewDebug(lView: LView) {
|
||||||
attachDebugObject(lView, new LViewDebug(lView));
|
attachDebugObject(lView, new LViewDebug(lView));
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, SchemaMetadata} from '../../me
|
||||||
import {validateAgainstEventProperties} from '../../sanitization/sanitization';
|
import {validateAgainstEventProperties} from '../../sanitization/sanitization';
|
||||||
import {Sanitizer} from '../../sanitization/security';
|
import {Sanitizer} from '../../sanitization/security';
|
||||||
import {assertDataInRange, assertDefined, assertDomNode, assertEqual, assertLessThan, assertNotEqual, assertNotSame} from '../../util/assert';
|
import {assertDataInRange, assertDefined, assertDomNode, assertEqual, assertLessThan, assertNotEqual, assertNotSame} from '../../util/assert';
|
||||||
|
import {createNamedArrayType} from '../../util/named_array_type';
|
||||||
import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../../util/ng_reflect';
|
import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../../util/ng_reflect';
|
||||||
import {assertLView, assertPreviousIsParent} from '../assert';
|
import {assertLView, assertPreviousIsParent} from '../assert';
|
||||||
import {attachPatchData, getComponentViewByInstance} from '../context_discovery';
|
import {attachPatchData, getComponentViewByInstance} from '../context_discovery';
|
||||||
|
@ -37,7 +38,8 @@ import {attrsStylingIndexOf} from '../util/attrs_utils';
|
||||||
import {INTERPOLATION_DELIMITER, stringifyForError} from '../util/misc_utils';
|
import {INTERPOLATION_DELIMITER, stringifyForError} from '../util/misc_utils';
|
||||||
import {getLViewParent, getRootContext} from '../util/view_traversal_utils';
|
import {getLViewParent, getRootContext} from '../util/view_traversal_utils';
|
||||||
import {getComponentViewByIndex, getNativeByIndex, getNativeByTNode, getTNode, isComponent, isComponentDef, isContentQueryHost, isLContainer, isRootView, readPatchedLView, resetPreOrderHookFlags, unwrapRNode, viewAttachedToChangeDetector} from '../util/view_utils';
|
import {getComponentViewByIndex, getNativeByIndex, getNativeByTNode, getTNode, isComponent, isComponentDef, isContentQueryHost, isLContainer, isRootView, readPatchedLView, resetPreOrderHookFlags, unwrapRNode, viewAttachedToChangeDetector} from '../util/view_utils';
|
||||||
import {attachLContainerDebug, attachLViewDebug} from './lview_debug';
|
|
||||||
|
import {LCleanup, LViewBlueprint, MatchesArray, TCleanup, TNodeInitialData, TNodeInitialInputs, TNodeLocalNames, TViewComponents, TViewConstructor, attachLContainerDebug, attachLViewDebug, cloneToLView, cloneToTViewData} from './lview_debug';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -199,13 +201,12 @@ export function elementCreate(name: string, overriddenRenderer?: Renderer3): REl
|
||||||
}
|
}
|
||||||
return native;
|
return native;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createLView<T>(
|
export function createLView<T>(
|
||||||
parentLView: LView | null, tView: TView, context: T | null, flags: LViewFlags,
|
parentLView: LView | null, tView: TView, context: T | null, flags: LViewFlags,
|
||||||
host: RElement | null, tHostNode: TViewNode | TElementNode | null,
|
host: RElement | null, tHostNode: TViewNode | TElementNode | null,
|
||||||
rendererFactory?: RendererFactory3 | null, renderer?: Renderer3 | null,
|
rendererFactory?: RendererFactory3 | null, renderer?: Renderer3 | null,
|
||||||
sanitizer?: Sanitizer | null, injector?: Injector | null): LView {
|
sanitizer?: Sanitizer | null, injector?: Injector | null): LView {
|
||||||
const lView = tView.blueprint.slice() as LView;
|
const lView = ngDevMode ? cloneToLView(tView.blueprint) : tView.blueprint.slice() as LView;
|
||||||
lView[HOST] = host;
|
lView[HOST] = host;
|
||||||
lView[FLAGS] = flags | LViewFlags.CreationMode | LViewFlags.Attached | LViewFlags.FirstLViewPass;
|
lView[FLAGS] = flags | LViewFlags.CreationMode | LViewFlags.Attached | LViewFlags.FirstLViewPass;
|
||||||
resetPreOrderHookFlags(lView);
|
resetPreOrderHookFlags(lView);
|
||||||
|
@ -553,6 +554,7 @@ export function getOrCreateTView(def: ComponentDef<any>): TView {
|
||||||
def.viewQuery, def.schemas));
|
def.viewQuery, def.schemas));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a TView instance
|
* Creates a TView instance
|
||||||
*
|
*
|
||||||
|
@ -575,38 +577,71 @@ export function createTView(
|
||||||
// that has a host binding, we will update the blueprint with that def's hostVars count.
|
// that has a host binding, we will update the blueprint with that def's hostVars count.
|
||||||
const initialViewLength = bindingStartIndex + vars;
|
const initialViewLength = bindingStartIndex + vars;
|
||||||
const blueprint = createViewBlueprint(bindingStartIndex, initialViewLength);
|
const blueprint = createViewBlueprint(bindingStartIndex, initialViewLength);
|
||||||
return blueprint[TVIEW as any] = {
|
return blueprint[TVIEW as any] = ngDevMode ?
|
||||||
id: viewIndex,
|
new TViewConstructor(
|
||||||
blueprint: blueprint,
|
viewIndex, // id: number,
|
||||||
template: templateFn,
|
blueprint, // blueprint: LView,
|
||||||
viewQuery: viewQuery,
|
templateFn, // template: ComponentTemplate<{}>|null,
|
||||||
node: null !,
|
viewQuery, // viewQuery: ViewQueriesFunction<{}>|null,
|
||||||
data: blueprint.slice().fill(null, bindingStartIndex),
|
null !, // node: TViewNode|TElementNode|null,
|
||||||
bindingStartIndex: bindingStartIndex,
|
cloneToTViewData(blueprint).fill(null, bindingStartIndex), // data: TData,
|
||||||
viewQueryStartIndex: initialViewLength,
|
bindingStartIndex, // bindingStartIndex: number,
|
||||||
expandoStartIndex: initialViewLength,
|
initialViewLength, // viewQueryStartIndex: number,
|
||||||
expandoInstructions: null,
|
initialViewLength, // expandoStartIndex: number,
|
||||||
firstTemplatePass: true,
|
null, // expandoInstructions: ExpandoInstructions|null,
|
||||||
staticViewQueries: false,
|
true, // firstTemplatePass: boolean,
|
||||||
staticContentQueries: false,
|
false, // staticViewQueries: boolean,
|
||||||
preOrderHooks: null,
|
false, // staticContentQueries: boolean,
|
||||||
preOrderCheckHooks: null,
|
null, // preOrderHooks: HookData|null,
|
||||||
contentHooks: null,
|
null, // preOrderCheckHooks: HookData|null,
|
||||||
contentCheckHooks: null,
|
null, // contentHooks: HookData|null,
|
||||||
viewHooks: null,
|
null, // contentCheckHooks: HookData|null,
|
||||||
viewCheckHooks: null,
|
null, // viewHooks: HookData|null,
|
||||||
destroyHooks: null,
|
null, // viewCheckHooks: HookData|null,
|
||||||
cleanup: null,
|
null, // destroyHooks: HookData|null,
|
||||||
contentQueries: null,
|
null, // cleanup: any[]|null,
|
||||||
components: null,
|
null, // contentQueries: number[]|null,
|
||||||
directiveRegistry: typeof directives === 'function' ? directives() : directives,
|
null, // components: number[]|null,
|
||||||
pipeRegistry: typeof pipes === 'function' ? pipes() : pipes,
|
typeof directives === 'function' ?
|
||||||
firstChild: null,
|
directives() :
|
||||||
schemas: schemas,
|
directives, // directiveRegistry: DirectiveDefList|null,
|
||||||
};
|
typeof pipes === 'function' ? pipes() : pipes, // pipeRegistry: PipeDefList|null,
|
||||||
|
null, // firstChild: TNode|null,
|
||||||
|
schemas, // schemas: SchemaMetadata[]|null,
|
||||||
|
) :
|
||||||
|
{
|
||||||
|
id: viewIndex,
|
||||||
|
blueprint: blueprint,
|
||||||
|
template: templateFn,
|
||||||
|
viewQuery: viewQuery,
|
||||||
|
node: null !,
|
||||||
|
data: blueprint.slice().fill(null, bindingStartIndex),
|
||||||
|
bindingStartIndex: bindingStartIndex,
|
||||||
|
viewQueryStartIndex: initialViewLength,
|
||||||
|
expandoStartIndex: initialViewLength,
|
||||||
|
expandoInstructions: null,
|
||||||
|
firstTemplatePass: true,
|
||||||
|
staticViewQueries: false,
|
||||||
|
staticContentQueries: false,
|
||||||
|
preOrderHooks: null,
|
||||||
|
preOrderCheckHooks: null,
|
||||||
|
contentHooks: null,
|
||||||
|
contentCheckHooks: null,
|
||||||
|
viewHooks: null,
|
||||||
|
viewCheckHooks: null,
|
||||||
|
destroyHooks: null,
|
||||||
|
cleanup: null,
|
||||||
|
contentQueries: null,
|
||||||
|
components: null,
|
||||||
|
directiveRegistry: typeof directives === 'function' ? directives() : directives,
|
||||||
|
pipeRegistry: typeof pipes === 'function' ? pipes() : pipes,
|
||||||
|
firstChild: null,
|
||||||
|
schemas: schemas,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function createViewBlueprint(bindingStartIndex: number, initialViewLength: number): LView {
|
function createViewBlueprint(bindingStartIndex: number, initialViewLength: number): LView {
|
||||||
const blueprint = new Array(initialViewLength)
|
const blueprint = new (ngDevMode ? LViewBlueprint ! : Array)(initialViewLength)
|
||||||
.fill(null, 0, bindingStartIndex)
|
.fill(null, 0, bindingStartIndex)
|
||||||
.fill(NO_CHANGE, bindingStartIndex) as LView;
|
.fill(NO_CHANGE, bindingStartIndex) as LView;
|
||||||
blueprint[BINDING_INDEX] = bindingStartIndex;
|
blueprint[BINDING_INDEX] = bindingStartIndex;
|
||||||
|
@ -1132,7 +1167,6 @@ function postProcessBaseDirective<T>(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches the current node against all available selectors.
|
* Matches the current node against all available selectors.
|
||||||
* If a component is matched (at most one), it is returned in first position in the array.
|
* If a component is matched (at most one), it is returned in first position in the array.
|
||||||
|
@ -1146,7 +1180,7 @@ function findDirectiveMatches(tView: TView, viewData: LView, tNode: TNode): Dire
|
||||||
for (let i = 0; i < registry.length; i++) {
|
for (let i = 0; i < registry.length; i++) {
|
||||||
const def = registry[i] as ComponentDef<any>| DirectiveDef<any>;
|
const def = registry[i] as ComponentDef<any>| DirectiveDef<any>;
|
||||||
if (isNodeMatchingSelectorList(tNode, def.selectors !, /* isProjectionMode */ false)) {
|
if (isNodeMatchingSelectorList(tNode, def.selectors !, /* isProjectionMode */ false)) {
|
||||||
matches || (matches = []);
|
matches || (matches = ngDevMode ? new MatchesArray !() : []);
|
||||||
diPublicInInjector(
|
diPublicInInjector(
|
||||||
getOrCreateNodeInjectorForNode(
|
getOrCreateNodeInjectorForNode(
|
||||||
getPreviousOrParentTNode() as TElementNode | TContainerNode | TElementContainerNode,
|
getPreviousOrParentTNode() as TElementNode | TContainerNode | TElementContainerNode,
|
||||||
|
@ -1173,7 +1207,8 @@ export function queueComponentIndexForCheck(previousOrParentTNode: TNode): void
|
||||||
const tView = getLView()[TVIEW];
|
const tView = getLView()[TVIEW];
|
||||||
ngDevMode &&
|
ngDevMode &&
|
||||||
assertEqual(tView.firstTemplatePass, true, 'Should only be called in first template pass.');
|
assertEqual(tView.firstTemplatePass, true, 'Should only be called in first template pass.');
|
||||||
(tView.components || (tView.components = [])).push(previousOrParentTNode.index);
|
(tView.components || (tView.components = ngDevMode ? new TViewComponents !() : [
|
||||||
|
])).push(previousOrParentTNode.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1181,7 +1216,8 @@ export function queueComponentIndexForCheck(previousOrParentTNode: TNode): void
|
||||||
function cacheMatchingLocalNames(
|
function cacheMatchingLocalNames(
|
||||||
tNode: TNode, localRefs: string[] | null, exportsMap: {[key: string]: number}): void {
|
tNode: TNode, localRefs: string[] | null, exportsMap: {[key: string]: number}): void {
|
||||||
if (localRefs) {
|
if (localRefs) {
|
||||||
const localNames: (string | number)[] = tNode.localNames = [];
|
const localNames: (string | number)[] = tNode.localNames =
|
||||||
|
ngDevMode ? new TNodeLocalNames !() : [];
|
||||||
|
|
||||||
// Local names must be stored in tNode in the same order that localRefs are defined
|
// Local names must be stored in tNode in the same order that localRefs are defined
|
||||||
// in the template to ensure the data is loaded in the same slots as their refs
|
// in the template to ensure the data is loaded in the same slots as their refs
|
||||||
|
@ -1320,7 +1356,8 @@ function setInputsFromAttrs<T>(
|
||||||
*/
|
*/
|
||||||
function generateInitialInputs(
|
function generateInitialInputs(
|
||||||
directiveIndex: number, inputs: {[key: string]: string}, tNode: TNode): InitialInputData {
|
directiveIndex: number, inputs: {[key: string]: string}, tNode: TNode): InitialInputData {
|
||||||
const initialInputData: InitialInputData = tNode.initialInputs || (tNode.initialInputs = []);
|
const initialInputData: InitialInputData =
|
||||||
|
tNode.initialInputs || (tNode.initialInputs = ngDevMode ? new TNodeInitialInputs !() : []);
|
||||||
// Ensure that we don't create sparse arrays
|
// Ensure that we don't create sparse arrays
|
||||||
for (let i = initialInputData.length; i <= directiveIndex; i++) {
|
for (let i = initialInputData.length; i <= directiveIndex; i++) {
|
||||||
initialInputData.push(null);
|
initialInputData.push(null);
|
||||||
|
@ -1347,8 +1384,8 @@ function generateInitialInputs(
|
||||||
const attrValue = attrs[i + 1];
|
const attrValue = attrs[i + 1];
|
||||||
|
|
||||||
if (minifiedInputName !== undefined) {
|
if (minifiedInputName !== undefined) {
|
||||||
const inputsToStore: InitialInputs =
|
const inputsToStore: InitialInputs = initialInputData[directiveIndex] ||
|
||||||
initialInputData[directiveIndex] || (initialInputData[directiveIndex] = []);
|
(initialInputData[directiveIndex] = ngDevMode ? new TNodeInitialData !() : []);
|
||||||
inputsToStore.push(attrName as string, minifiedInputName, attrValue as string);
|
inputsToStore.push(attrName as string, minifiedInputName, attrValue as string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1361,6 +1398,9 @@ function generateInitialInputs(
|
||||||
//// ViewContainer & View
|
//// ViewContainer & View
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
|
|
||||||
|
// Not sure why I need to do `any` here but TS complains later.
|
||||||
|
const LContainerArray: any = ngDevMode && createNamedArrayType('LContainer');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a LContainer, either from a container instruction, or for a ViewContainerRef.
|
* Creates a LContainer, either from a container instruction, or for a ViewContainerRef.
|
||||||
*
|
*
|
||||||
|
@ -1376,16 +1416,17 @@ export function createLContainer(
|
||||||
tNode: TNode, isForViewContainerRef?: boolean): LContainer {
|
tNode: TNode, isForViewContainerRef?: boolean): LContainer {
|
||||||
ngDevMode && assertDomNode(native);
|
ngDevMode && assertDomNode(native);
|
||||||
ngDevMode && assertLView(currentView);
|
ngDevMode && assertLView(currentView);
|
||||||
const lContainer: LContainer = [
|
// https://jsperf.com/array-literal-vs-new-array-really
|
||||||
hostNative, // host native
|
const lContainer: LContainer = new (ngDevMode ? LContainerArray : Array)(
|
||||||
true, // Boolean `true` in this position signifies that this is an `LContainer`
|
hostNative, // host native
|
||||||
isForViewContainerRef ? -1 : 0, // active index
|
true, // Boolean `true` in this position signifies that this is an `LContainer`
|
||||||
currentView, // parent
|
isForViewContainerRef ? -1 : 0, // active index
|
||||||
null, // next
|
currentView, // parent
|
||||||
null, // queries
|
null, // next
|
||||||
tNode, // t_host
|
null, // queries
|
||||||
native, // native
|
tNode, // t_host
|
||||||
];
|
native, // native
|
||||||
|
);
|
||||||
ngDevMode && attachLContainerDebug(lContainer);
|
ngDevMode && attachLContainerDebug(lContainer);
|
||||||
return lContainer;
|
return lContainer;
|
||||||
}
|
}
|
||||||
|
@ -1711,14 +1752,13 @@ export function initializeTNodeInputs(tNode: TNode): PropertyAliases|null {
|
||||||
return tNode.inputs;
|
return tNode.inputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function getCleanup(view: LView): any[] {
|
export function getCleanup(view: LView): any[] {
|
||||||
// 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 view[CLEANUP] || (view[CLEANUP] = []);
|
return view[CLEANUP] || (view[CLEANUP] = ngDevMode ? new LCleanup !() : []);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTViewCleanup(view: LView): any[] {
|
function getTViewCleanup(view: LView): any[] {
|
||||||
return view[TVIEW].cleanup || (view[TVIEW].cleanup = []);
|
return view[TVIEW].cleanup || (view[TVIEW].cleanup = ngDevMode ? new TCleanup !() : []);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import './ng_dev_mode';
|
||||||
|
import {global} from './global';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* THIS FILE CONTAINS CODE WHICH SHOULD BE TREE SHAKEN AND NEVER CALLED FROM PRODUCTION CODE!!!
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an `Array` construction with a given name. This is useful when
|
||||||
|
* looking for memory consumption to see what time of array it is.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param name Name to give to the constructor
|
||||||
|
* @returns A subclass of `Array` if possible. This can only be done in
|
||||||
|
* environments which support `class` construct.
|
||||||
|
*/
|
||||||
|
export function createNamedArrayType(name: string): typeof Array {
|
||||||
|
// This should never be called in prod mode, so let's verify that is the case.
|
||||||
|
if (ngDevMode) {
|
||||||
|
try {
|
||||||
|
// We need to do it this way so that TypeScript does not down-level the below code.
|
||||||
|
const FunctionConstructor: any = createNamedArrayType.constructor;
|
||||||
|
return (new FunctionConstructor('Array', `return class ABC extends Array{}`))(Array);
|
||||||
|
} catch (e) {
|
||||||
|
// If it does not work just give up and fall back to regular Array.
|
||||||
|
return Array;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
'Looks like we are in \'prod mode\', but we are creating a named Array type, which is wrong! Check your code');
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ import {global} from './global';
|
||||||
declare global {
|
declare global {
|
||||||
const ngDevMode: null|NgDevModePerfCounters;
|
const ngDevMode: null|NgDevModePerfCounters;
|
||||||
interface NgDevModePerfCounters {
|
interface NgDevModePerfCounters {
|
||||||
|
namedConstructors: boolean;
|
||||||
firstTemplatePass: number;
|
firstTemplatePass: number;
|
||||||
tNode: number;
|
tNode: number;
|
||||||
tView: number;
|
tView: number;
|
||||||
|
@ -45,7 +46,9 @@ declare global {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ngDevModeResetPerfCounters(): NgDevModePerfCounters {
|
export function ngDevModeResetPerfCounters(): NgDevModePerfCounters {
|
||||||
|
const locationString = typeof location !== 'undefined' ? location.toString() : '';
|
||||||
const newCounters: NgDevModePerfCounters = {
|
const newCounters: NgDevModePerfCounters = {
|
||||||
|
namedConstructors: locationString.indexOf('ngDevMode=namedConstructors') != -1,
|
||||||
firstTemplatePass: 0,
|
firstTemplatePass: 0,
|
||||||
tNode: 0,
|
tNode: 0,
|
||||||
tView: 0,
|
tView: 0,
|
||||||
|
@ -79,7 +82,8 @@ export function ngDevModeResetPerfCounters(): NgDevModePerfCounters {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Make sure to refer to ngDevMode as ['ngDevMode'] for closure.
|
// Make sure to refer to ngDevMode as ['ngDevMode'] for closure.
|
||||||
global['ngDevMode'] = newCounters;
|
const allowNgDevModeTrue = locationString.indexOf('ngDevMode=false') === -1;
|
||||||
|
global['ngDevMode'] = allowNgDevModeTrue && newCounters;
|
||||||
return newCounters;
|
return newCounters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {CompilerStylingMode, compilerSetStylingMode} from '@angular/compiler/src
|
||||||
import {Component, Directive, HostBinding, Input, ViewChild} from '@angular/core';
|
import {Component, Directive, HostBinding, Input, ViewChild} from '@angular/core';
|
||||||
import {SecurityContext} from '@angular/core/src/core';
|
import {SecurityContext} from '@angular/core/src/core';
|
||||||
import {getLContext} from '@angular/core/src/render3/context_discovery';
|
import {getLContext} from '@angular/core/src/render3/context_discovery';
|
||||||
import {DebugNode, LViewDebug, toDebug} from '@angular/core/src/render3/debug';
|
import {DebugNode, LViewDebug, toDebug} from '@angular/core/src/render3/instructions/lview_debug';
|
||||||
import {SANITIZER} from '@angular/core/src/render3/interfaces/view';
|
import {SANITIZER} from '@angular/core/src/render3/interfaces/view';
|
||||||
import {RuntimeStylingMode, runtimeSetStylingMode, setCurrentStyleSanitizer} from '@angular/core/src/render3/styling_next/state';
|
import {RuntimeStylingMode, runtimeSetStylingMode, setCurrentStyleSanitizer} from '@angular/core/src/render3/styling_next/state';
|
||||||
import {loadLContextFromNode} from '@angular/core/src/render3/util/discovery_utils';
|
import {loadLContextFromNode} from '@angular/core/src/render3/util/discovery_utils';
|
||||||
|
|
Loading…
Reference in New Issue