fix(core): Store the currently selected ICU in LView (#38345)
The currently selected ICU was incorrectly being stored it `TNode` rather than in `LView`. Remove: `TIcuContainerNode.activeCaseIndex` Add: `LView[TIcu.currentCaseIndex]` PR Close #38345
This commit is contained in:
committed by
Andrew Kushnir
parent
6ff28ac944
commit
6d8c73a4d6
@@ -62,7 +62,7 @@
|
||||
"bundle": "TODO(i): we should define ngDevMode to false in Closure, but --define only works in the global scope.",
|
||||
"bundle": "TODO(i): (FW-2164) TS 3.9 new class shape seems to have broken Closure in big ways. The size went from 169991 to 252338",
|
||||
"bundle": "TODO(i): after removal of tsickle from ngc-wrapped / ng_package, we had to switch to SIMPLE optimizations which increased the size from 252338 to 1198917, see PR#37221 and PR#37317 for more info",
|
||||
"bundle": 1213130
|
||||
"bundle": 1213769
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import {devModeEqual} from '../change_detection/change_detection_util';
|
||||
import {assertDataInRange, assertLessThan, assertNotSame} from '../util/assert';
|
||||
import {assertIndexInRange, assertLessThan, assertNotSame} from '../util/assert';
|
||||
|
||||
import {getExpressionChangedErrorDetails, throwErrorIfNoChangesMode} from './errors';
|
||||
import {LView} from './interfaces/view';
|
||||
@@ -24,7 +24,7 @@ export function updateBinding(lView: LView, bindingIndex: number, value: any): a
|
||||
|
||||
/** Gets the current binding value. */
|
||||
export function getBinding(lView: LView, bindingIndex: number): any {
|
||||
ngDevMode && assertDataInRange(lView, bindingIndex);
|
||||
ngDevMode && assertIndexInRange(lView, bindingIndex);
|
||||
ngDevMode &&
|
||||
assertNotSame(lView[bindingIndex], NO_CHANGE, 'Stored value should never be NO_CHANGE.');
|
||||
return lView[bindingIndex];
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
import {Type} from '../core';
|
||||
import {Injector} from '../di/injector';
|
||||
import {Sanitizer} from '../sanitization/sanitizer';
|
||||
import {assertDataInRange} from '../util/assert';
|
||||
import {assertIndexInRange} from '../util/assert';
|
||||
|
||||
import {assertComponentType} from './assert';
|
||||
import {getComponentDef} from './definition';
|
||||
@@ -172,7 +172,7 @@ export function createRootComponentView(
|
||||
rNode: RElement|null, def: ComponentDef<any>, rootView: LView,
|
||||
rendererFactory: RendererFactory3, hostRenderer: Renderer3, sanitizer?: Sanitizer|null): LView {
|
||||
const tView = rootView[TVIEW];
|
||||
ngDevMode && assertDataInRange(rootView, 0 + HEADER_OFFSET);
|
||||
ngDevMode && assertIndexInRange(rootView, 0 + HEADER_OFFSET);
|
||||
rootView[0 + HEADER_OFFSET] = rNode;
|
||||
const tNode: TElementNode = getOrCreateTNode(tView, null, 0, TNodeType.Element, null, null);
|
||||
const mergedAttrs = tNode.mergedAttrs = def.hostAttrs;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
* 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 {assertDataInRange, assertGreaterThan} from '../../util/assert';
|
||||
import {assertGreaterThan, assertIndexInRange} from '../../util/assert';
|
||||
import {executeCheckHooks, executeInitAndCheckHooks} from '../hooks';
|
||||
import {FLAGS, HEADER_OFFSET, InitPhaseState, LView, LViewFlags, TView} from '../interfaces/view';
|
||||
import {getCheckNoChangesMode, getLView, getSelectedIndex, getTView, setSelectedIndex} from '../state';
|
||||
@@ -52,7 +52,7 @@ export function ɵɵselect(index: number): void {
|
||||
export function selectIndexInternal(
|
||||
tView: TView, lView: LView, index: number, checkNoChangesMode: boolean) {
|
||||
ngDevMode && assertGreaterThan(index, -1, 'Invalid index');
|
||||
ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
|
||||
ngDevMode && assertIndexInRange(lView, index + HEADER_OFFSET);
|
||||
|
||||
// Flush the initial hooks for elements in the view that have been added up to this point.
|
||||
// PERF WARNING: do NOT extract this to a separate function without running benchmarks
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {assertDataInRange, assertDefined, assertEqual} from '../../util/assert';
|
||||
import {assertDefined, assertEqual, assertIndexInRange} from '../../util/assert';
|
||||
import {assertFirstCreatePass, assertHasParent} from '../assert';
|
||||
import {attachPatchData} from '../context_discovery';
|
||||
import {registerPostOrderHooks} from '../hooks';
|
||||
@@ -79,7 +79,7 @@ export function ɵɵelementStart(
|
||||
getBindingIndex(), tView.bindingStartIndex,
|
||||
'elements should be created before any bindings');
|
||||
ngDevMode && ngDevMode.rendererCreateElement++;
|
||||
ngDevMode && assertDataInRange(lView, adjustedIndex);
|
||||
ngDevMode && assertIndexInRange(lView, adjustedIndex);
|
||||
|
||||
const renderer = lView[RENDERER];
|
||||
const native = lView[adjustedIndex] = elementCreate(name, renderer, getNamespace());
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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 {assertDataInRange, assertEqual} from '../../util/assert';
|
||||
import {assertEqual, assertIndexInRange} from '../../util/assert';
|
||||
import {assertHasParent} from '../assert';
|
||||
import {attachPatchData} from '../context_discovery';
|
||||
import {registerPostOrderHooks} from '../hooks';
|
||||
@@ -66,7 +66,7 @@ export function ɵɵelementContainerStart(
|
||||
const tView = getTView();
|
||||
const adjustedIndex = index + HEADER_OFFSET;
|
||||
|
||||
ngDevMode && assertDataInRange(lView, adjustedIndex);
|
||||
ngDevMode && assertIndexInRange(lView, adjustedIndex);
|
||||
ngDevMode &&
|
||||
assertEqual(
|
||||
getBindingIndex(), tView.bindingStartIndex,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
|
||||
import {assertDataInRange} from '../../util/assert';
|
||||
import {assertIndexInRange} from '../../util/assert';
|
||||
import {isObservable} from '../../util/lang';
|
||||
import {EMPTY_OBJ} from '../empty';
|
||||
import {PropertyAliasValue, TNode, TNodeFlags, TNodeType} from '../interfaces/node';
|
||||
@@ -204,7 +204,7 @@ function listenerInternal(
|
||||
if (propsLength) {
|
||||
for (let i = 0; i < propsLength; i += 2) {
|
||||
const index = props[i] as number;
|
||||
ngDevMode && assertDataInRange(lView, index);
|
||||
ngDevMode && assertIndexInRange(lView, index);
|
||||
const minifiedName = props[i + 1];
|
||||
const directiveInstance = lView[index];
|
||||
const output = directiveInstance[minifiedName];
|
||||
|
||||
@@ -362,19 +362,24 @@ export function toDebug(obj: any): any {
|
||||
* (will not serialize child elements).
|
||||
*/
|
||||
function toHtml(value: any, includeChildren: boolean = false): string|null {
|
||||
const node: HTMLElement|null = unwrapRNode(value) as any;
|
||||
const node: Node|null = unwrapRNode(value) as any;
|
||||
if (node) {
|
||||
const isTextNode = node.nodeType === Node.TEXT_NODE;
|
||||
const outerHTML = (isTextNode ? node.textContent : node.outerHTML) || '';
|
||||
if (includeChildren || isTextNode) {
|
||||
return outerHTML;
|
||||
} else {
|
||||
const innerHTML = '>' + node.innerHTML + '<';
|
||||
return (outerHTML.split(innerHTML)[0]) + '>';
|
||||
switch (node.nodeType) {
|
||||
case Node.TEXT_NODE:
|
||||
return node.textContent;
|
||||
case Node.COMMENT_NODE:
|
||||
return `<!--${(node as Comment).textContent}-->`;
|
||||
case Node.ELEMENT_NODE:
|
||||
const outerHTML = (node as Element).outerHTML;
|
||||
if (includeChildren) {
|
||||
return outerHTML;
|
||||
} else {
|
||||
const innerHTML = '>' + (node as Element).innerHTML + '<';
|
||||
return (outerHTML.split(innerHTML)[0]) + '>';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export class LViewDebug implements ILViewDebug {
|
||||
|
||||
@@ -12,7 +12,7 @@ import {CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, SchemaMetadata} from '../../me
|
||||
import {ViewEncapsulation} from '../../metadata/view';
|
||||
import {validateAgainstEventAttributes, validateAgainstEventProperties} from '../../sanitization/sanitization';
|
||||
import {Sanitizer} from '../../sanitization/sanitizer';
|
||||
import {assertDataInRange, assertDefined, assertDomNode, assertEqual, assertGreaterThan, assertLessThan, assertNotEqual, assertNotSame, assertSame} from '../../util/assert';
|
||||
import {assertDefined, assertDomNode, assertEqual, assertGreaterThan, assertIndexInRange, assertLessThan, assertNotEqual, assertNotSame, assertSame} from '../../util/assert';
|
||||
import {createNamedArrayType} from '../../util/named_array_type';
|
||||
import {initNgDevMode} from '../../util/ng_dev_mode';
|
||||
import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../../util/ng_reflect';
|
||||
@@ -236,13 +236,6 @@ export function getOrCreateTNode(
|
||||
const tNode = tView.data[adjustedIndex] as TNode ||
|
||||
createTNodeAtIndex(tView, tHostNode, adjustedIndex, type, name, attrs);
|
||||
setPreviousOrParentTNode(tNode, true);
|
||||
if (ngDevMode) {
|
||||
// For performance reasons it is important that the tNode retains the same shape during runtime.
|
||||
// (To make sure that all of the code is monomorphic.) For this reason we seal the object to
|
||||
// prevent class transitions.
|
||||
// FIXME(misko): re-enable this once i18n code is compliant with this.
|
||||
// Object.seal(tNode);
|
||||
}
|
||||
return tNode as TElementNode & TViewNode & TContainerNode & TElementContainerNode &
|
||||
TProjectionNode & TIcuContainerNode;
|
||||
}
|
||||
@@ -665,44 +658,44 @@ export function createTView(
|
||||
// that has a host binding, we will update the blueprint with that def's hostVars count.
|
||||
const initialViewLength = bindingStartIndex + vars;
|
||||
const blueprint = createViewBlueprint(bindingStartIndex, initialViewLength);
|
||||
return blueprint[TVIEW as any] = ngDevMode ?
|
||||
const tView = blueprint[TVIEW as any] = ngDevMode ?
|
||||
new TViewConstructor(
|
||||
type,
|
||||
viewIndex, // id: number,
|
||||
blueprint, // blueprint: LView,
|
||||
templateFn, // template: ComponentTemplate<{}>|null,
|
||||
null, // queries: TQueries|null
|
||||
viewQuery, // viewQuery: ViewQueriesFunction<{}>|null,
|
||||
null!, // node: TViewNode|TElementNode|null,
|
||||
cloneToTViewData(blueprint).fill(null, bindingStartIndex), // data: TData,
|
||||
bindingStartIndex, // bindingStartIndex: number,
|
||||
initialViewLength, // expandoStartIndex: number,
|
||||
null, // expandoInstructions: ExpandoInstructions|null,
|
||||
true, // firstCreatePass: boolean,
|
||||
true, // firstUpdatePass: boolean,
|
||||
false, // staticViewQueries: boolean,
|
||||
false, // staticContentQueries: boolean,
|
||||
null, // preOrderHooks: HookData|null,
|
||||
null, // preOrderCheckHooks: HookData|null,
|
||||
null, // contentHooks: HookData|null,
|
||||
null, // contentCheckHooks: HookData|null,
|
||||
null, // viewHooks: HookData|null,
|
||||
null, // viewCheckHooks: HookData|null,
|
||||
null, // destroyHooks: DestroyHookData|null,
|
||||
null, // cleanup: any[]|null,
|
||||
null, // contentQueries: number[]|null,
|
||||
null, // components: number[]|null,
|
||||
typeof directives === 'function' ?
|
||||
directives() :
|
||||
directives, // directiveRegistry: DirectiveDefList|null,
|
||||
typeof pipes === 'function' ? pipes() : pipes, // pipeRegistry: PipeDefList|null,
|
||||
null, // firstChild: TNode|null,
|
||||
schemas, // schemas: SchemaMetadata[]|null,
|
||||
consts, // consts: TConstants|null
|
||||
false, // incompleteFirstPass: boolean
|
||||
decls, // ngDevMode only: decls
|
||||
vars, // ngDevMode only: vars
|
||||
) :
|
||||
type,
|
||||
viewIndex, // id: number,
|
||||
blueprint, // blueprint: LView,
|
||||
templateFn, // template: ComponentTemplate<{}>|null,
|
||||
null, // queries: TQueries|null
|
||||
viewQuery, // viewQuery: ViewQueriesFunction<{}>|null,
|
||||
null!, // node: TViewNode|TElementNode|null,
|
||||
cloneToTViewData(blueprint).fill(null, bindingStartIndex), // data: TData,
|
||||
bindingStartIndex, // bindingStartIndex: number,
|
||||
initialViewLength, // expandoStartIndex: number,
|
||||
null, // expandoInstructions: ExpandoInstructions|null,
|
||||
true, // firstCreatePass: boolean,
|
||||
true, // firstUpdatePass: boolean,
|
||||
false, // staticViewQueries: boolean,
|
||||
false, // staticContentQueries: boolean,
|
||||
null, // preOrderHooks: HookData|null,
|
||||
null, // preOrderCheckHooks: HookData|null,
|
||||
null, // contentHooks: HookData|null,
|
||||
null, // contentCheckHooks: HookData|null,
|
||||
null, // viewHooks: HookData|null,
|
||||
null, // viewCheckHooks: HookData|null,
|
||||
null, // destroyHooks: DestroyHookData|null,
|
||||
null, // cleanup: any[]|null,
|
||||
null, // contentQueries: number[]|null,
|
||||
null, // components: number[]|null,
|
||||
typeof directives === 'function' ?
|
||||
directives() :
|
||||
directives, // directiveRegistry: DirectiveDefList|null,
|
||||
typeof pipes === 'function' ? pipes() : pipes, // pipeRegistry: PipeDefList|null,
|
||||
null, // firstChild: TNode|null,
|
||||
schemas, // schemas: SchemaMetadata[]|null,
|
||||
consts, // consts: TConstants|null
|
||||
false, // incompleteFirstPass: boolean
|
||||
decls, // ngDevMode only: decls
|
||||
vars, // ngDevMode only: vars
|
||||
) :
|
||||
{
|
||||
type: type,
|
||||
id: viewIndex,
|
||||
@@ -736,6 +729,13 @@ export function createTView(
|
||||
consts: consts,
|
||||
incompleteFirstPass: false
|
||||
};
|
||||
if (ngDevMode) {
|
||||
// For performance reasons it is important that the tView retains the same shape during runtime.
|
||||
// (To make sure that all of the code is monomorphic.) For this reason we seal the object to
|
||||
// prevent class transitions.
|
||||
Object.seal(tView);
|
||||
}
|
||||
return tView;
|
||||
}
|
||||
|
||||
function createViewBlueprint(bindingStartIndex: number, initialViewLength: number): LView {
|
||||
@@ -825,71 +825,79 @@ export function createTNode(
|
||||
tagName: string|null, attrs: TAttributes|null): TNode {
|
||||
ngDevMode && ngDevMode.tNode++;
|
||||
let injectorIndex = tParent ? tParent.injectorIndex : -1;
|
||||
return ngDevMode ? new TNodeDebug(
|
||||
tView, // tView_: TView
|
||||
type, // type: TNodeType
|
||||
adjustedIndex, // index: number
|
||||
injectorIndex, // injectorIndex: number
|
||||
-1, // directiveStart: number
|
||||
-1, // directiveEnd: number
|
||||
-1, // directiveStylingLast: number
|
||||
null, // propertyBindings: number[]|null
|
||||
0, // flags: TNodeFlags
|
||||
0, // providerIndexes: TNodeProviderIndexes
|
||||
tagName, // tagName: string|null
|
||||
attrs, // attrs: (string|AttributeMarker|(string|SelectorFlags)[])[]|null
|
||||
null, // mergedAttrs
|
||||
null, // localNames: (string|number)[]|null
|
||||
undefined, // initialInputs: (string[]|null)[]|null|undefined
|
||||
null, // inputs: PropertyAliases|null
|
||||
null, // outputs: PropertyAliases|null
|
||||
null, // tViews: ITView|ITView[]|null
|
||||
null, // next: ITNode|null
|
||||
null, // projectionNext: ITNode|null
|
||||
null, // child: ITNode|null
|
||||
tParent, // parent: TElementNode|TContainerNode|null
|
||||
null, // projection: number|(ITNode|RNode[])[]|null
|
||||
null, // styles: string|null
|
||||
null, // stylesWithoutHost: string|null
|
||||
undefined, // residualStyles: string|null
|
||||
null, // classes: string|null
|
||||
null, // classesWithoutHost: string|null
|
||||
undefined, // residualClasses: string|null
|
||||
0 as any, // classBindings: TStylingRange;
|
||||
0 as any, // styleBindings: TStylingRange;
|
||||
) :
|
||||
{
|
||||
type: type,
|
||||
index: adjustedIndex,
|
||||
injectorIndex: injectorIndex,
|
||||
directiveStart: -1,
|
||||
directiveEnd: -1,
|
||||
directiveStylingLast: -1,
|
||||
propertyBindings: null,
|
||||
flags: 0,
|
||||
providerIndexes: 0,
|
||||
tagName: tagName,
|
||||
attrs: attrs,
|
||||
mergedAttrs: null,
|
||||
localNames: null,
|
||||
initialInputs: undefined,
|
||||
inputs: null,
|
||||
outputs: null,
|
||||
tViews: null,
|
||||
next: null,
|
||||
projectionNext: null,
|
||||
child: null,
|
||||
parent: tParent,
|
||||
projection: null,
|
||||
styles: null,
|
||||
stylesWithoutHost: null,
|
||||
residualStyles: undefined,
|
||||
classes: null,
|
||||
classesWithoutHost: null,
|
||||
residualClasses: undefined,
|
||||
classBindings: 0 as any,
|
||||
styleBindings: 0 as any,
|
||||
};
|
||||
const tNode = ngDevMode ?
|
||||
new TNodeDebug(
|
||||
tView, // tView_: TView
|
||||
type, // type: TNodeType
|
||||
adjustedIndex, // index: number
|
||||
injectorIndex, // injectorIndex: number
|
||||
-1, // directiveStart: number
|
||||
-1, // directiveEnd: number
|
||||
-1, // directiveStylingLast: number
|
||||
null, // propertyBindings: number[]|null
|
||||
0, // flags: TNodeFlags
|
||||
0, // providerIndexes: TNodeProviderIndexes
|
||||
tagName, // tagName: string|null
|
||||
attrs, // attrs: (string|AttributeMarker|(string|SelectorFlags)[])[]|null
|
||||
null, // mergedAttrs
|
||||
null, // localNames: (string|number)[]|null
|
||||
undefined, // initialInputs: (string[]|null)[]|null|undefined
|
||||
null, // inputs: PropertyAliases|null
|
||||
null, // outputs: PropertyAliases|null
|
||||
null, // tViews: ITView|ITView[]|null
|
||||
null, // next: ITNode|null
|
||||
null, // projectionNext: ITNode|null
|
||||
null, // child: ITNode|null
|
||||
tParent, // parent: TElementNode|TContainerNode|null
|
||||
null, // projection: number|(ITNode|RNode[])[]|null
|
||||
null, // styles: string|null
|
||||
null, // stylesWithoutHost: string|null
|
||||
undefined, // residualStyles: string|null
|
||||
null, // classes: string|null
|
||||
null, // classesWithoutHost: string|null
|
||||
undefined, // residualClasses: string|null
|
||||
0 as any, // classBindings: TStylingRange;
|
||||
0 as any, // styleBindings: TStylingRange;
|
||||
) :
|
||||
{
|
||||
type: type,
|
||||
index: adjustedIndex,
|
||||
injectorIndex: injectorIndex,
|
||||
directiveStart: -1,
|
||||
directiveEnd: -1,
|
||||
directiveStylingLast: -1,
|
||||
propertyBindings: null,
|
||||
flags: 0,
|
||||
providerIndexes: 0,
|
||||
tagName: tagName,
|
||||
attrs: attrs,
|
||||
mergedAttrs: null,
|
||||
localNames: null,
|
||||
initialInputs: undefined,
|
||||
inputs: null,
|
||||
outputs: null,
|
||||
tViews: null,
|
||||
next: null,
|
||||
projectionNext: null,
|
||||
child: null,
|
||||
parent: tParent,
|
||||
projection: null,
|
||||
styles: null,
|
||||
stylesWithoutHost: null,
|
||||
residualStyles: undefined,
|
||||
classes: null,
|
||||
classesWithoutHost: null,
|
||||
residualClasses: undefined,
|
||||
classBindings: 0 as any,
|
||||
styleBindings: 0 as any,
|
||||
};
|
||||
if (ngDevMode) {
|
||||
// For performance reasons it is important that the tNode retains the same shape during runtime.
|
||||
// (To make sure that all of the code is monomorphic.) For this reason we seal the object to
|
||||
// prevent class transitions.
|
||||
Object.seal(tNode);
|
||||
}
|
||||
return tNode;
|
||||
}
|
||||
|
||||
|
||||
@@ -2040,7 +2048,7 @@ export function setInputsForProperty(
|
||||
const index = inputs[i++] as number;
|
||||
const privateName = inputs[i++] as string;
|
||||
const instance = lView[index];
|
||||
ngDevMode && assertDataInRange(lView, index);
|
||||
ngDevMode && assertIndexInRange(lView, index);
|
||||
const def = tView.data[index] as DirectiveDef<any>;
|
||||
if (def.setInput !== null) {
|
||||
def.setInput!(instance, value, publicName, privateName);
|
||||
@@ -2055,7 +2063,7 @@ export function setInputsForProperty(
|
||||
*/
|
||||
export function textBindingInternal(lView: LView, index: number, value: string): void {
|
||||
ngDevMode && assertNotSame(value, NO_CHANGE as any, 'value should not be NO_CHANGE');
|
||||
ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
|
||||
ngDevMode && assertIndexInRange(lView, index + HEADER_OFFSET);
|
||||
const element = getNativeByIndex(index, lView) as any as RText;
|
||||
ngDevMode && assertDefined(element, 'native element should exist');
|
||||
ngDevMode && ngDevMode.rendererSetText++;
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
* 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 {assertDataInRange, assertEqual} from '../../util/assert';
|
||||
import {assertEqual, assertIndexInRange} from '../../util/assert';
|
||||
import {TElementNode, TNodeType} from '../interfaces/node';
|
||||
import {HEADER_OFFSET, RENDERER, T_HOST} from '../interfaces/view';
|
||||
import {appendChild, createTextNode} from '../node_manipulation';
|
||||
import {getBindingIndex, getLView, getTView, setPreviousOrParentTNode} from '../state';
|
||||
|
||||
import {getOrCreateTNode} from './shared';
|
||||
|
||||
|
||||
@@ -31,7 +32,7 @@ export function ɵɵtext(index: number, value: string = ''): void {
|
||||
assertEqual(
|
||||
getBindingIndex(), tView.bindingStartIndex,
|
||||
'text nodes should be created before any bindings');
|
||||
ngDevMode && assertDataInRange(lView, adjustedIndex);
|
||||
ngDevMode && assertIndexInRange(lView, adjustedIndex);
|
||||
|
||||
const tNode = tView.firstCreatePass ?
|
||||
getOrCreateTNode(tView, lView[T_HOST], index, TNodeType.Element, null, null) :
|
||||
|
||||
@@ -346,6 +346,14 @@ export interface TIcu {
|
||||
*/
|
||||
vars: number[];
|
||||
|
||||
/**
|
||||
* Currently selected ICU case pointer.
|
||||
*
|
||||
* `lView[currentCaseLViewIndex]` stores the currently selected case. This is needed to know how
|
||||
* to clean up the current case when transitioning no the new case.
|
||||
*/
|
||||
currentCaseLViewIndex: number;
|
||||
|
||||
/**
|
||||
* An optional array of child/sub ICUs.
|
||||
*
|
||||
|
||||
@@ -709,13 +709,6 @@ export interface TIcuContainerNode extends TNode {
|
||||
parent: TElementNode|TElementContainerNode|null;
|
||||
tViews: null;
|
||||
projection: null;
|
||||
/**
|
||||
* Indicates the current active case for an ICU expression.
|
||||
* It is null when there is no active case.
|
||||
*
|
||||
*/
|
||||
// FIXME(misko): This is at a wrong location as activeCase is `LView` (not `TView`) concern
|
||||
activeCaseIndex: number|null;
|
||||
}
|
||||
|
||||
/** Static data for a view */
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {assertDataInRange} from '../util/assert';
|
||||
import {assertIndexInRange} from '../util/assert';
|
||||
import {bindingUpdated, bindingUpdated2, bindingUpdated3, bindingUpdated4, getBinding, updateBinding} from './bindings';
|
||||
import {LView} from './interfaces/view';
|
||||
import {getBindingRoot, getLView} from './state';
|
||||
@@ -287,7 +287,7 @@ export function ɵɵpureFunctionV(
|
||||
* it to `undefined`.
|
||||
*/
|
||||
function getPureFunctionReturnValue(lView: LView, returnValueIndex: number) {
|
||||
ngDevMode && assertDataInRange(lView, returnValueIndex);
|
||||
ngDevMode && assertIndexInRange(lView, returnValueIndex);
|
||||
const lastReturnValue = lView[returnValueIndex];
|
||||
return lastReturnValue === NO_CHANGE ? undefined : lastReturnValue;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import {ElementRef as ViewEngine_ElementRef} from '../linker/element_ref';
|
||||
import {QueryList} from '../linker/query_list';
|
||||
import {TemplateRef as ViewEngine_TemplateRef} from '../linker/template_ref';
|
||||
import {ViewContainerRef} from '../linker/view_container_ref';
|
||||
import {assertDataInRange, assertDefined, throwError} from '../util/assert';
|
||||
import {assertDefined, assertIndexInRange, throwError} from '../util/assert';
|
||||
import {stringify} from '../util/stringify';
|
||||
|
||||
import {assertFirstCreatePass, assertLContainer} from './assert';
|
||||
@@ -140,7 +140,7 @@ class TQueries_ implements TQueries {
|
||||
}
|
||||
|
||||
getByIndex(index: number): TQuery {
|
||||
ngDevMode && assertDataInRange(this.queries, index);
|
||||
ngDevMode && assertIndexInRange(this.queries, index);
|
||||
return this.queries[index];
|
||||
}
|
||||
|
||||
@@ -358,7 +358,7 @@ function materializeViewResults<T>(
|
||||
// null as a placeholder
|
||||
result.push(null);
|
||||
} else {
|
||||
ngDevMode && assertDataInRange(tViewData, matchedNodeIdx);
|
||||
ngDevMode && assertIndexInRange(tViewData, matchedNodeIdx);
|
||||
const tNode = tViewData[matchedNodeIdx] as TNode;
|
||||
result.push(createResultForNode(lView, tNode, tQueryMatches[i + 1], tQuery.metadata.read));
|
||||
}
|
||||
@@ -551,7 +551,7 @@ export function ɵɵloadQuery<T>(): QueryList<T> {
|
||||
function loadQueryInternal<T>(lView: LView, queryIndex: number): QueryList<T> {
|
||||
ngDevMode &&
|
||||
assertDefined(lView[QUERIES], 'LQueries should be defined when trying to load a query');
|
||||
ngDevMode && assertDataInRange(lView[QUERIES]!.queries, queryIndex);
|
||||
ngDevMode && assertIndexInRange(lView[QUERIES]!.queries, queryIndex);
|
||||
return lView[QUERIES]!.queries[queryIndex].queryList;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import {KeyValueArray, keyValueArrayIndexOf} from '../../util/array_utils';
|
||||
import {assertDataInRange, assertEqual, assertNotEqual} from '../../util/assert';
|
||||
import {assertEqual, assertIndexInRange, assertNotEqual} from '../../util/assert';
|
||||
import {assertFirstUpdatePass} from '../assert';
|
||||
import {TNode} from '../interfaces/node';
|
||||
import {getTStylingRangeNext, getTStylingRangePrev, setTStylingRangeNext, setTStylingRangeNextDuplicate, setTStylingRangePrev, setTStylingRangePrevDuplicate, toTStylingRange, TStylingKey, TStylingKeyPrimitive, TStylingRange} from '../interfaces/styling';
|
||||
@@ -370,7 +370,7 @@ function markDuplicates(
|
||||
// - we are a map in which case we have to continue searching even after we find what we were
|
||||
// looking for since we are a wild card and everything needs to be flipped to duplicate.
|
||||
while (cursor !== 0 && (foundDuplicate === false || isMap)) {
|
||||
ngDevMode && assertDataInRange(tData, cursor);
|
||||
ngDevMode && assertIndexInRange(tData, cursor);
|
||||
const tStylingValueAtCursor = tData[cursor] as TStylingKey;
|
||||
const tStyleRangeAtCursor = tData[cursor + 1] as TStylingRange;
|
||||
if (isStylingMatch(tStylingValueAtCursor, tStylingKey)) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {assertDataInRange, assertDefined, assertDomNode, assertGreaterThan, assertLessThan} from '../../util/assert';
|
||||
import {assertDefined, assertDomNode, assertGreaterThan, assertIndexInRange, assertLessThan} from '../../util/assert';
|
||||
import {assertTNodeForLView} from '../assert';
|
||||
import {LContainer, TYPE} from '../interfaces/container';
|
||||
import {LContext, MONKEY_PATCH_KEY_NAME} from '../interfaces/context';
|
||||
@@ -91,7 +91,7 @@ export function getNativeByIndex(index: number, lView: LView): RNode {
|
||||
*/
|
||||
export function getNativeByTNode(tNode: TNode, lView: LView): RNode {
|
||||
ngDevMode && assertTNodeForLView(tNode, lView);
|
||||
ngDevMode && assertDataInRange(lView, tNode.index);
|
||||
ngDevMode && assertIndexInRange(lView, tNode.index);
|
||||
const node: RNode = unwrapRNode(lView[tNode.index]);
|
||||
ngDevMode && !isProceduralRenderer(lView[RENDERER]) && assertDomNode(node);
|
||||
return node;
|
||||
@@ -125,13 +125,13 @@ export function getTNode(tView: TView, index: number): TNode {
|
||||
|
||||
/** Retrieves a value from any `LView` or `TData`. */
|
||||
export function load<T>(view: LView|TData, index: number): T {
|
||||
ngDevMode && assertDataInRange(view, index + HEADER_OFFSET);
|
||||
ngDevMode && assertIndexInRange(view, index + HEADER_OFFSET);
|
||||
return view[index + HEADER_OFFSET];
|
||||
}
|
||||
|
||||
export function getComponentLViewByIndex(nodeIndex: number, hostView: LView): LView {
|
||||
// Could be an LView or an LContainer. If LContainer, unwrap to find LView.
|
||||
ngDevMode && assertDataInRange(hostView, nodeIndex);
|
||||
ngDevMode && assertIndexInRange(hostView, nodeIndex);
|
||||
const slotValue = hostView[nodeIndex];
|
||||
const lView = isLView(slotValue) ? slotValue : slotValue[HOST];
|
||||
return lView;
|
||||
|
||||
@@ -110,7 +110,7 @@ export function assertDomNode(node: any): asserts node is Node {
|
||||
}
|
||||
|
||||
|
||||
export function assertDataInRange(arr: any[], index: number) {
|
||||
export function assertIndexInRange(arr: any[], index: number) {
|
||||
const maxLen = arr ? arr.length : 0;
|
||||
assertLessThan(index, maxLen, `Index expected to be less than ${maxLen} but got ${index}`);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -261,7 +261,7 @@ describe('Runtime i18n', () => {
|
||||
}, null, nbConsts, index) as TI18n;
|
||||
|
||||
expect(opCodes).toEqual({
|
||||
vars: 5,
|
||||
vars: 6,
|
||||
update: debugMatch([
|
||||
'if (mask & 0b1) { icuSwitchCase(lView[1] as Comment, 0, `${lView[1]}`); }',
|
||||
'if (mask & 0b11) { icuUpdateCase(lView[1] as Comment, 0); }',
|
||||
@@ -272,60 +272,61 @@ describe('Runtime i18n', () => {
|
||||
]),
|
||||
icus: [<TIcu>{
|
||||
type: 1,
|
||||
vars: [4, 3, 3],
|
||||
currentCaseLViewIndex: 22,
|
||||
vars: [5, 4, 4],
|
||||
childIcus: [[], [], []],
|
||||
cases: ['0', '1', 'other'],
|
||||
create: [
|
||||
debugMatch([
|
||||
'lView[2] = document.createTextNode("no ")',
|
||||
'(lView[1] as Element).appendChild(lView[2])',
|
||||
'lView[3] = document.createElement("b")',
|
||||
'lView[3] = document.createTextNode("no ")',
|
||||
'(lView[1] as Element).appendChild(lView[3])',
|
||||
'(lView[3] as Element).setAttribute("title", "none")',
|
||||
'lView[4] = document.createTextNode("emails")',
|
||||
'(lView[3] as Element).appendChild(lView[4])',
|
||||
'lView[5] = document.createTextNode("!")',
|
||||
'(lView[1] as Element).appendChild(lView[5])'
|
||||
'lView[4] = document.createElement("b")',
|
||||
'(lView[1] as Element).appendChild(lView[4])',
|
||||
'(lView[4] as Element).setAttribute("title", "none")',
|
||||
'lView[5] = document.createTextNode("emails")',
|
||||
'(lView[4] as Element).appendChild(lView[5])',
|
||||
'lView[6] = document.createTextNode("!")',
|
||||
'(lView[1] as Element).appendChild(lView[6])',
|
||||
]),
|
||||
debugMatch([
|
||||
'lView[2] = document.createTextNode("one ")',
|
||||
'(lView[1] as Element).appendChild(lView[2])',
|
||||
'lView[3] = document.createElement("i")',
|
||||
'lView[3] = document.createTextNode("one ")',
|
||||
'(lView[1] as Element).appendChild(lView[3])',
|
||||
'lView[4] = document.createTextNode("email")',
|
||||
'(lView[3] as Element).appendChild(lView[4])'
|
||||
'lView[4] = document.createElement("i")',
|
||||
'(lView[1] as Element).appendChild(lView[4])',
|
||||
'lView[5] = document.createTextNode("email")',
|
||||
'(lView[4] as Element).appendChild(lView[5])',
|
||||
]),
|
||||
debugMatch([
|
||||
'lView[2] = document.createTextNode("")',
|
||||
'(lView[1] as Element).appendChild(lView[2])',
|
||||
'lView[3] = document.createElement("span")',
|
||||
'lView[3] = document.createTextNode("")',
|
||||
'(lView[1] as Element).appendChild(lView[3])',
|
||||
'lView[4] = document.createTextNode("emails")',
|
||||
'(lView[3] as Element).appendChild(lView[4])'
|
||||
'lView[4] = document.createElement("span")',
|
||||
'(lView[1] as Element).appendChild(lView[4])',
|
||||
'lView[5] = document.createTextNode("emails")',
|
||||
'(lView[4] as Element).appendChild(lView[5])',
|
||||
])
|
||||
],
|
||||
remove: [
|
||||
debugMatch([
|
||||
'(lView[0] as Element).remove(lView[2])',
|
||||
'(lView[0] as Element).remove(lView[4])',
|
||||
'(lView[0] as Element).remove(lView[3])',
|
||||
'(lView[0] as Element).remove(lView[5])',
|
||||
'(lView[0] as Element).remove(lView[4])',
|
||||
'(lView[0] as Element).remove(lView[6])',
|
||||
]),
|
||||
debugMatch([
|
||||
'(lView[0] as Element).remove(lView[2])',
|
||||
'(lView[0] as Element).remove(lView[4])',
|
||||
'(lView[0] as Element).remove(lView[3])',
|
||||
'(lView[0] as Element).remove(lView[5])',
|
||||
'(lView[0] as Element).remove(lView[4])',
|
||||
]),
|
||||
debugMatch([
|
||||
'(lView[0] as Element).remove(lView[2])',
|
||||
'(lView[0] as Element).remove(lView[4])',
|
||||
'(lView[0] as Element).remove(lView[3])',
|
||||
'(lView[0] as Element).remove(lView[5])',
|
||||
'(lView[0] as Element).remove(lView[4])',
|
||||
])
|
||||
],
|
||||
update: [
|
||||
debugMatch([]), debugMatch([]), debugMatch([
|
||||
'if (mask & 0b1) { (lView[2] as Text).textContent = `${lView[1]} `; }',
|
||||
'if (mask & 0b10) { (lView[3] as Element).setAttribute(\'title\', `${lView[2]}`); }'
|
||||
'if (mask & 0b1) { (lView[3] as Text).textContent = `${lView[1]} `; }',
|
||||
'if (mask & 0b10) { (lView[4] as Element).setAttribute(\'title\', `${lView[2]}`); }'
|
||||
])
|
||||
]
|
||||
}]
|
||||
@@ -355,7 +356,7 @@ describe('Runtime i18n', () => {
|
||||
const nestedTIcuIndex = 0;
|
||||
|
||||
expect(opCodes).toEqual({
|
||||
vars: 6,
|
||||
vars: 9,
|
||||
create: debugMatch([
|
||||
'lView[1] = document.createComment("ICU 1")',
|
||||
'(lView[0] as Element).appendChild(lView[1])'
|
||||
@@ -367,27 +368,28 @@ describe('Runtime i18n', () => {
|
||||
icus: [
|
||||
{
|
||||
type: 0,
|
||||
vars: [1, 1, 1],
|
||||
vars: [2, 2, 2],
|
||||
currentCaseLViewIndex: 26,
|
||||
childIcus: [[], [], []],
|
||||
cases: ['cat', 'dog', 'other'],
|
||||
create: [
|
||||
debugMatch([
|
||||
'lView[5] = document.createTextNode("cats")',
|
||||
'(lView[3] as Element).appendChild(lView[5])'
|
||||
'lView[7] = document.createTextNode("cats")',
|
||||
'(lView[4] as Element).appendChild(lView[7])'
|
||||
]),
|
||||
debugMatch([
|
||||
'lView[5] = document.createTextNode("dogs")',
|
||||
'(lView[3] as Element).appendChild(lView[5])'
|
||||
'lView[7] = document.createTextNode("dogs")',
|
||||
'(lView[4] as Element).appendChild(lView[7])'
|
||||
]),
|
||||
debugMatch([
|
||||
'lView[5] = document.createTextNode("animals")',
|
||||
'(lView[3] as Element).appendChild(lView[5])'
|
||||
'lView[7] = document.createTextNode("animals")',
|
||||
'(lView[4] as Element).appendChild(lView[7])'
|
||||
]),
|
||||
],
|
||||
remove: [
|
||||
debugMatch(['(lView[0] as Element).remove(lView[5])']),
|
||||
debugMatch(['(lView[0] as Element).remove(lView[5])']),
|
||||
debugMatch(['(lView[0] as Element).remove(lView[5])'])
|
||||
debugMatch(['(lView[0] as Element).remove(lView[7])']),
|
||||
debugMatch(['(lView[0] as Element).remove(lView[7])']),
|
||||
debugMatch(['(lView[0] as Element).remove(lView[7])'])
|
||||
],
|
||||
update: [
|
||||
debugMatch([]),
|
||||
@@ -397,36 +399,37 @@ describe('Runtime i18n', () => {
|
||||
},
|
||||
{
|
||||
type: 1,
|
||||
vars: [1, 4],
|
||||
vars: [2, 6],
|
||||
childIcus: [[], [0]],
|
||||
currentCaseLViewIndex: 22,
|
||||
cases: ['0', 'other'],
|
||||
create: [
|
||||
debugMatch([
|
||||
'lView[2] = document.createTextNode("zero")',
|
||||
'(lView[1] as Element).appendChild(lView[2])'
|
||||
'lView[3] = document.createTextNode("zero")',
|
||||
'(lView[1] as Element).appendChild(lView[3])'
|
||||
]),
|
||||
debugMatch([
|
||||
'lView[2] = document.createTextNode("")',
|
||||
'(lView[1] as Element).appendChild(lView[2])',
|
||||
'lView[3] = document.createComment("nested ICU 0")',
|
||||
'lView[3] = document.createTextNode("")',
|
||||
'(lView[1] as Element).appendChild(lView[3])',
|
||||
'lView[4] = document.createTextNode("!")',
|
||||
'(lView[1] as Element).appendChild(lView[4])'
|
||||
'lView[4] = document.createComment("nested ICU 0")',
|
||||
'(lView[1] as Element).appendChild(lView[4])',
|
||||
'lView[5] = document.createTextNode("!")',
|
||||
'(lView[1] as Element).appendChild(lView[5])'
|
||||
]),
|
||||
],
|
||||
remove: [
|
||||
debugMatch(['(lView[0] as Element).remove(lView[2])']),
|
||||
debugMatch(['(lView[0] as Element).remove(lView[3])']),
|
||||
debugMatch([
|
||||
'(lView[0] as Element).remove(lView[2])', '(lView[0] as Element).remove(lView[4])',
|
||||
'removeNestedICU(0)', '(lView[0] as Element).remove(lView[3])'
|
||||
'(lView[0] as Element).remove(lView[3])', '(lView[0] as Element).remove(lView[5])',
|
||||
'removeNestedICU(0)', '(lView[0] as Element).remove(lView[4])'
|
||||
]),
|
||||
],
|
||||
update: [
|
||||
debugMatch([]),
|
||||
debugMatch([
|
||||
'if (mask & 0b1) { (lView[2] as Text).textContent = `${lView[1]} `; }',
|
||||
'if (mask & 0b10) { icuSwitchCase(lView[3] as Comment, 0, `${lView[2]}`); }',
|
||||
'if (mask & 0b10) { icuUpdateCase(lView[3] as Comment, 0); }'
|
||||
'if (mask & 0b1) { (lView[3] as Text).textContent = `${lView[1]} `; }',
|
||||
'if (mask & 0b10) { icuSwitchCase(lView[4] as Comment, 0, `${lView[2]}`); }',
|
||||
'if (mask & 0b10) { icuUpdateCase(lView[4] as Comment, 0); }'
|
||||
]),
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user