refactor(ivy): t-functions should not depend on l-data (#30453)

PR Close #30453
This commit is contained in:
Misko Hevery 2019-05-15 20:59:55 -07:00 committed by Jason Aden
parent 2f336f15be
commit 5c5cee9f39
9 changed files with 40 additions and 38 deletions

View File

@ -11,6 +11,7 @@
import {Type} from '../core';
import {Injector} from '../di/injector';
import {Sanitizer} from '../sanitization/security';
import {assertDataInRange, assertEqual} from '../util/assert';
import {assertComponentType} from './assert';
import {getComponentDef} from './definition';
@ -172,7 +173,9 @@ export function createRootComponentView(
rendererFactory: RendererFactory3, renderer: Renderer3, sanitizer?: Sanitizer | null): LView {
resetComponentState();
const tView = rootView[TVIEW];
const tNode: TElementNode = createNodeAtIndex(0, TNodeType.Element, rNode, null, null);
ngDevMode && assertDataInRange(rootView, 0 + HEADER_OFFSET);
rootView[0 + HEADER_OFFSET] = rNode;
const tNode: TElementNode = createNodeAtIndex(0, TNodeType.Element, null, null);
const componentView = createLView(
rootView, getOrCreateTView(def), null, def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways,
rootView[HEADER_OFFSET], tNode, rendererFactory, renderer, sanitizer);

View File

@ -12,7 +12,7 @@ import {SRCSET_ATTRS, URI_ATTRS, VALID_ATTRS, VALID_ELEMENTS, getTemplateContent
import {InertBodyHelper} from '../sanitization/inert_body';
import {_sanitizeUrl, sanitizeSrcset} from '../sanitization/url_sanitizer';
import {addAllToArray} from '../util/array_utils';
import {assertDefined, assertEqual, assertGreaterThan} from '../util/assert';
import {assertDataInRange, assertDefined, assertEqual, assertGreaterThan} from '../util/assert';
import {attachPatchData} from './context_discovery';
import {attachI18nOpCodesDebug} from './debug';
@ -671,10 +671,12 @@ function i18nEndFirstPass(tView: TView) {
* Creates and stores the dynamic TNode, and unhooks it from the tree for now.
*/
function createDynamicNodeAtIndex(
index: number, type: TNodeType, native: RElement | RText | null,
lView: LView, index: number, type: TNodeType, native: RElement | RText | null,
name: string | null): TElementNode|TIcuContainerNode {
const previousOrParentTNode = getPreviousOrParentTNode();
const tNode = createNodeAtIndex(index, type as any, native, name, null);
ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
lView[index + HEADER_OFFSET] = native;
const tNode = createNodeAtIndex(index, type as any, name, null);
// We are creating a dynamic node, the previous tNode might not be pointing at this node.
// We will link ourselves into the tree later with `appendI18nNode`.
@ -699,7 +701,8 @@ function readCreateOpCodes(
const textNodeIndex = createOpCodes[++i] as number;
ngDevMode && ngDevMode.rendererCreateTextNode++;
previousTNode = currentTNode;
currentTNode = createDynamicNodeAtIndex(textNodeIndex, TNodeType.Element, textRNode, null);
currentTNode =
createDynamicNodeAtIndex(viewData, textNodeIndex, TNodeType.Element, textRNode, null);
visitedNodes.push(textNodeIndex);
setIsNotParent();
} else if (typeof opCode == 'number') {
@ -755,7 +758,7 @@ function readCreateOpCodes(
ngDevMode && ngDevMode.rendererCreateComment++;
previousTNode = currentTNode;
currentTNode = createDynamicNodeAtIndex(
commentNodeIndex, TNodeType.IcuContainer, commentRNode, null);
viewData, commentNodeIndex, TNodeType.IcuContainer, commentRNode, null);
visitedNodes.push(commentNodeIndex);
attachPatchData(commentRNode, viewData);
(currentTNode as TIcuContainerNode).activeCaseIndex = null;
@ -772,7 +775,7 @@ function readCreateOpCodes(
ngDevMode && ngDevMode.rendererCreateElement++;
previousTNode = currentTNode;
currentTNode = createDynamicNodeAtIndex(
elementNodeIndex, TNodeType.Element, elementRNode, tagNameValue);
viewData, elementNodeIndex, TNodeType.Element, elementRNode, tagNameValue);
visitedNodes.push(elementNodeIndex);
break;
default:

View File

@ -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 {assertEqual} from '../../util/assert';
import {assertDataInRange, assertEqual} from '../../util/assert';
import {assertHasParent} from '../assert';
import {attachPatchData} from '../context_discovery';
import {executePreOrderHooks, registerPostOrderHooks} from '../hooks';
@ -164,9 +164,11 @@ function containerInternal(
'container nodes should be created before any bindings');
const adjustedIndex = index + HEADER_OFFSET;
const comment = lView[RENDERER].createComment(ngDevMode ? 'container' : '');
ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
ngDevMode && ngDevMode.rendererCreateComment++;
const tNode = createNodeAtIndex(index, TNodeType.Container, comment, tagName, attrs);
const comment = lView[index + HEADER_OFFSET] =
lView[RENDERER].createComment(ngDevMode ? 'container' : '');
const tNode = createNodeAtIndex(index, TNodeType.Container, tagName, attrs);
const lContainer = lView[adjustedIndex] =
createLContainer(lView[adjustedIndex], lView, comment, tNode);

View File

@ -14,7 +14,7 @@ import {TAttributes, TNodeFlags, TNodeType} from '../interfaces/node';
import {RElement, isProceduralRenderer} from '../interfaces/renderer';
import {SanitizerFn} from '../interfaces/sanitization';
import {StylingContext} from '../interfaces/styling';
import {BINDING_INDEX, QUERIES, RENDERER, TVIEW} from '../interfaces/view';
import {BINDING_INDEX, HEADER_OFFSET, QUERIES, RENDERER, TVIEW} from '../interfaces/view';
import {assertNodeType} from '../node_assert';
import {appendChild} from '../node_manipulation';
import {applyOnCreateInstructions} from '../node_util';
@ -55,13 +55,10 @@ export function ɵɵelementStart(
'elements should be created before any bindings ');
ngDevMode && ngDevMode.rendererCreateElement++;
const native = elementCreate(name);
ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
const native = lView[index + HEADER_OFFSET] = elementCreate(name);
const renderer = lView[RENDERER];
ngDevMode && assertDataInRange(lView, index - 1);
const tNode = createNodeAtIndex(index, TNodeType.Element, native !, name, attrs || null);
const tNode = createNodeAtIndex(index, TNodeType.Element, name, attrs || null);
let initialStylesIndex = 0;
let initialClassesIndex = 0;

View File

@ -10,7 +10,7 @@ import {assertHasParent} from '../assert';
import {attachPatchData} from '../context_discovery';
import {registerPostOrderHooks} from '../hooks';
import {TAttributes, TNodeType} from '../interfaces/node';
import {BINDING_INDEX, QUERIES, RENDERER, TVIEW} from '../interfaces/view';
import {BINDING_INDEX, HEADER_OFFSET, QUERIES, RENDERER, TVIEW} from '../interfaces/view';
import {assertNodeType} from '../node_assert';
import {appendChild} from '../node_manipulation';
import {applyOnCreateInstructions} from '../node_util';
@ -43,11 +43,11 @@ export function ɵɵelementContainerStart(
'element containers should be created before any bindings');
ngDevMode && ngDevMode.rendererCreateComment++;
const native = renderer.createComment(ngDevMode ? tagName : '');
ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
const native = lView[index + HEADER_OFFSET] = renderer.createComment(ngDevMode ? tagName : '');
ngDevMode && assertDataInRange(lView, index - 1);
const tNode =
createNodeAtIndex(index, TNodeType.ElementContainer, native, tagName, attrs || null);
const tNode = createNodeAtIndex(index, TNodeType.ElementContainer, tagName, attrs || null);
if (attrs) {

View File

@ -5,9 +5,10 @@
* 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} from '../../util/assert';
import {TAttributes, TElementNode, TNode, TNodeType} from '../interfaces/node';
import {CssSelectorList} from '../interfaces/projection';
import {T_HOST} from '../interfaces/view';
import {HEADER_OFFSET, T_HOST} from '../interfaces/view';
import {appendProjectedNodes} from '../node_manipulation';
import {matchingProjectionSelectorIndex} from '../node_selector_matcher';
import {getLView, setIsNotParent} from '../state';
@ -81,8 +82,7 @@ export function ɵɵprojectionDef(selectors?: CssSelectorList[]): void {
export function ɵɵprojection(
nodeIndex: number, selectorIndex: number = 0, attrs?: TAttributes): void {
const lView = getLView();
const tProjectionNode =
createNodeAtIndex(nodeIndex, TNodeType.Projection, null, null, attrs || null);
const tProjectionNode = createNodeAtIndex(nodeIndex, TNodeType.Projection, null, attrs || null);
// We can't use viewData[HOST_NODE] because projection nodes can be nested in embedded views.
if (tProjectionNode.projection === null) tProjectionNode.projection = selectorIndex;

View File

@ -233,30 +233,26 @@ export function createLView<T>(
* @param attrs Any attrs for the native element, if applicable
*/
export function createNodeAtIndex(
index: number, type: TNodeType.Element, native: RElement | RText | null, name: string | null,
index: number, type: TNodeType.Element, name: string | null,
attrs: TAttributes | null): TElementNode;
export function createNodeAtIndex(
index: number, type: TNodeType.Container, native: RComment, name: string | null,
index: number, type: TNodeType.Container, name: string | null,
attrs: TAttributes | null): TContainerNode;
export function createNodeAtIndex(
index: number, type: TNodeType.Projection, native: null, name: null,
index: number, type: TNodeType.Projection, name: null,
attrs: TAttributes | null): TProjectionNode;
export function createNodeAtIndex(
index: number, type: TNodeType.ElementContainer, native: RComment, name: string | null,
index: number, type: TNodeType.ElementContainer, name: string | null,
attrs: TAttributes | null): TElementContainerNode;
export function createNodeAtIndex(
index: number, type: TNodeType.IcuContainer, native: RComment, name: null,
index: number, type: TNodeType.IcuContainer, name: null,
attrs: TAttributes | null): TElementContainerNode;
export function createNodeAtIndex(
index: number, type: TNodeType, native: RText | RElement | RComment | null, name: string | null,
attrs: TAttributes | null): TElementNode&TContainerNode&TElementContainerNode&TProjectionNode&
TIcuContainerNode {
index: number, type: TNodeType, name: string | null, attrs: TAttributes | null): TElementNode&
TContainerNode&TElementContainerNode&TProjectionNode&TIcuContainerNode {
const lView = getLView();
const tView = lView[TVIEW];
const adjustedIndex = index + HEADER_OFFSET;
ngDevMode &&
assertLessThan(adjustedIndex, lView.length, `Slot should have been initialized with null`);
lView[adjustedIndex] = native;
const previousOrParentTNode = getPreviousOrParentTNode();
let tNode = tView.data[adjustedIndex] as TNode;

View File

@ -30,8 +30,9 @@ export function ɵɵtext(index: number, value?: any): void {
lView[BINDING_INDEX], lView[TVIEW].bindingStartIndex,
'text nodes should be created before any bindings');
ngDevMode && ngDevMode.rendererCreateTextNode++;
const textNative = createTextNode(value, lView[RENDERER]);
const tNode = createNodeAtIndex(index, TNodeType.Element, textNative, null, null);
ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
const textNative = lView[index + HEADER_OFFSET] = createTextNode(value, lView[RENDERER]);
const tNode = createNodeAtIndex(index, TNodeType.Element, null, null);
// Text nodes are self closing.
setIsNotParent();

View File

@ -605,7 +605,7 @@ describe('di', () => {
null, null, {} as any, {} as any);
const oldView = enterView(contentView, null);
try {
const parentTNode = createNodeAtIndex(0, TNodeType.Element, null, null, null);
const parentTNode = createNodeAtIndex(0, TNodeType.Element, null, null);
// Simulate the situation where the previous parent is not initialized.
// This happens on first bootstrap because we don't init existing values
// so that we have smaller HelloWorld.