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 {Type} from '../core';
import {Injector} from '../di/injector'; import {Injector} from '../di/injector';
import {Sanitizer} from '../sanitization/security'; import {Sanitizer} from '../sanitization/security';
import {assertDataInRange, assertEqual} from '../util/assert';
import {assertComponentType} from './assert'; import {assertComponentType} from './assert';
import {getComponentDef} from './definition'; import {getComponentDef} from './definition';
@ -172,7 +173,9 @@ export function createRootComponentView(
rendererFactory: RendererFactory3, renderer: Renderer3, sanitizer?: Sanitizer | null): LView { rendererFactory: RendererFactory3, renderer: Renderer3, sanitizer?: Sanitizer | null): LView {
resetComponentState(); resetComponentState();
const tView = rootView[TVIEW]; 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( const componentView = createLView(
rootView, getOrCreateTView(def), null, def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways, rootView, getOrCreateTView(def), null, def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways,
rootView[HEADER_OFFSET], tNode, rendererFactory, renderer, sanitizer); 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 {InertBodyHelper} from '../sanitization/inert_body';
import {_sanitizeUrl, sanitizeSrcset} from '../sanitization/url_sanitizer'; import {_sanitizeUrl, sanitizeSrcset} from '../sanitization/url_sanitizer';
import {addAllToArray} from '../util/array_utils'; 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 {attachPatchData} from './context_discovery';
import {attachI18nOpCodesDebug} from './debug'; 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. * Creates and stores the dynamic TNode, and unhooks it from the tree for now.
*/ */
function createDynamicNodeAtIndex( 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 { name: string | null): TElementNode|TIcuContainerNode {
const previousOrParentTNode = getPreviousOrParentTNode(); 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 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`. // We will link ourselves into the tree later with `appendI18nNode`.
@ -699,7 +701,8 @@ function readCreateOpCodes(
const textNodeIndex = createOpCodes[++i] as number; const textNodeIndex = createOpCodes[++i] as number;
ngDevMode && ngDevMode.rendererCreateTextNode++; ngDevMode && ngDevMode.rendererCreateTextNode++;
previousTNode = currentTNode; previousTNode = currentTNode;
currentTNode = createDynamicNodeAtIndex(textNodeIndex, TNodeType.Element, textRNode, null); currentTNode =
createDynamicNodeAtIndex(viewData, textNodeIndex, TNodeType.Element, textRNode, null);
visitedNodes.push(textNodeIndex); visitedNodes.push(textNodeIndex);
setIsNotParent(); setIsNotParent();
} else if (typeof opCode == 'number') { } else if (typeof opCode == 'number') {
@ -755,7 +758,7 @@ function readCreateOpCodes(
ngDevMode && ngDevMode.rendererCreateComment++; ngDevMode && ngDevMode.rendererCreateComment++;
previousTNode = currentTNode; previousTNode = currentTNode;
currentTNode = createDynamicNodeAtIndex( currentTNode = createDynamicNodeAtIndex(
commentNodeIndex, TNodeType.IcuContainer, commentRNode, null); viewData, commentNodeIndex, TNodeType.IcuContainer, commentRNode, null);
visitedNodes.push(commentNodeIndex); visitedNodes.push(commentNodeIndex);
attachPatchData(commentRNode, viewData); attachPatchData(commentRNode, viewData);
(currentTNode as TIcuContainerNode).activeCaseIndex = null; (currentTNode as TIcuContainerNode).activeCaseIndex = null;
@ -772,7 +775,7 @@ function readCreateOpCodes(
ngDevMode && ngDevMode.rendererCreateElement++; ngDevMode && ngDevMode.rendererCreateElement++;
previousTNode = currentTNode; previousTNode = currentTNode;
currentTNode = createDynamicNodeAtIndex( currentTNode = createDynamicNodeAtIndex(
elementNodeIndex, TNodeType.Element, elementRNode, tagNameValue); viewData, elementNodeIndex, TNodeType.Element, elementRNode, tagNameValue);
visitedNodes.push(elementNodeIndex); visitedNodes.push(elementNodeIndex);
break; break;
default: default:

View File

@ -5,7 +5,7 @@
* Use of this source code is governed by an MIT-style license that can be * 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 * 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 {assertHasParent} from '../assert';
import {attachPatchData} from '../context_discovery'; import {attachPatchData} from '../context_discovery';
import {executePreOrderHooks, registerPostOrderHooks} from '../hooks'; import {executePreOrderHooks, registerPostOrderHooks} from '../hooks';
@ -164,9 +164,11 @@ function containerInternal(
'container nodes should be created before any bindings'); 'container nodes should be created before any bindings');
const adjustedIndex = index + HEADER_OFFSET; const adjustedIndex = index + HEADER_OFFSET;
const comment = lView[RENDERER].createComment(ngDevMode ? 'container' : ''); ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
ngDevMode && ngDevMode.rendererCreateComment++; 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] = const lContainer = lView[adjustedIndex] =
createLContainer(lView[adjustedIndex], lView, comment, tNode); 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 {RElement, isProceduralRenderer} from '../interfaces/renderer';
import {SanitizerFn} from '../interfaces/sanitization'; import {SanitizerFn} from '../interfaces/sanitization';
import {StylingContext} from '../interfaces/styling'; 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 {assertNodeType} from '../node_assert';
import {appendChild} from '../node_manipulation'; import {appendChild} from '../node_manipulation';
import {applyOnCreateInstructions} from '../node_util'; import {applyOnCreateInstructions} from '../node_util';
@ -55,13 +55,10 @@ export function ɵɵelementStart(
'elements should be created before any bindings '); 'elements should be created before any bindings ');
ngDevMode && ngDevMode.rendererCreateElement++; ngDevMode && ngDevMode.rendererCreateElement++;
ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
const native = elementCreate(name); const native = lView[index + HEADER_OFFSET] = elementCreate(name);
const renderer = lView[RENDERER]; const renderer = lView[RENDERER];
const tNode = createNodeAtIndex(index, TNodeType.Element, name, attrs || null);
ngDevMode && assertDataInRange(lView, index - 1);
const tNode = createNodeAtIndex(index, TNodeType.Element, native !, name, attrs || null);
let initialStylesIndex = 0; let initialStylesIndex = 0;
let initialClassesIndex = 0; let initialClassesIndex = 0;

View File

@ -10,7 +10,7 @@ import {assertHasParent} from '../assert';
import {attachPatchData} from '../context_discovery'; import {attachPatchData} from '../context_discovery';
import {registerPostOrderHooks} from '../hooks'; import {registerPostOrderHooks} from '../hooks';
import {TAttributes, TNodeType} from '../interfaces/node'; 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 {assertNodeType} from '../node_assert';
import {appendChild} from '../node_manipulation'; import {appendChild} from '../node_manipulation';
import {applyOnCreateInstructions} from '../node_util'; import {applyOnCreateInstructions} from '../node_util';
@ -43,11 +43,11 @@ export function ɵɵelementContainerStart(
'element containers should be created before any bindings'); 'element containers should be created before any bindings');
ngDevMode && ngDevMode.rendererCreateComment++; 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); ngDevMode && assertDataInRange(lView, index - 1);
const tNode = const tNode = createNodeAtIndex(index, TNodeType.ElementContainer, tagName, attrs || null);
createNodeAtIndex(index, TNodeType.ElementContainer, native, tagName, attrs || null);
if (attrs) { if (attrs) {

View File

@ -5,9 +5,10 @@
* Use of this source code is governed by an MIT-style license that can be * 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 * found in the LICENSE file at https://angular.io/license
*/ */
import {assertDataInRange} from '../../util/assert';
import {TAttributes, TElementNode, TNode, TNodeType} from '../interfaces/node'; import {TAttributes, TElementNode, TNode, TNodeType} from '../interfaces/node';
import {CssSelectorList} from '../interfaces/projection'; 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 {appendProjectedNodes} from '../node_manipulation';
import {matchingProjectionSelectorIndex} from '../node_selector_matcher'; import {matchingProjectionSelectorIndex} from '../node_selector_matcher';
import {getLView, setIsNotParent} from '../state'; import {getLView, setIsNotParent} from '../state';
@ -81,8 +82,7 @@ export function ɵɵprojectionDef(selectors?: CssSelectorList[]): void {
export function ɵɵprojection( export function ɵɵprojection(
nodeIndex: number, selectorIndex: number = 0, attrs?: TAttributes): void { nodeIndex: number, selectorIndex: number = 0, attrs?: TAttributes): void {
const lView = getLView(); const lView = getLView();
const tProjectionNode = const tProjectionNode = createNodeAtIndex(nodeIndex, TNodeType.Projection, null, attrs || null);
createNodeAtIndex(nodeIndex, TNodeType.Projection, null, null, attrs || null);
// We can't use viewData[HOST_NODE] because projection nodes can be nested in embedded views. // We can't use viewData[HOST_NODE] because projection nodes can be nested in embedded views.
if (tProjectionNode.projection === null) tProjectionNode.projection = selectorIndex; 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 * @param attrs Any attrs for the native element, if applicable
*/ */
export function createNodeAtIndex( 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; attrs: TAttributes | null): TElementNode;
export function createNodeAtIndex( 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; attrs: TAttributes | null): TContainerNode;
export function createNodeAtIndex( export function createNodeAtIndex(
index: number, type: TNodeType.Projection, native: null, name: null, index: number, type: TNodeType.Projection, name: null,
attrs: TAttributes | null): TProjectionNode; attrs: TAttributes | null): TProjectionNode;
export function createNodeAtIndex( 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; attrs: TAttributes | null): TElementContainerNode;
export function createNodeAtIndex( export function createNodeAtIndex(
index: number, type: TNodeType.IcuContainer, native: RComment, name: null, index: number, type: TNodeType.IcuContainer, name: null,
attrs: TAttributes | null): TElementContainerNode; attrs: TAttributes | null): TElementContainerNode;
export function createNodeAtIndex( export function createNodeAtIndex(
index: number, type: TNodeType, native: RText | RElement | RComment | null, name: string | null, index: number, type: TNodeType, name: string | null, attrs: TAttributes | null): TElementNode&
attrs: TAttributes | null): TElementNode&TContainerNode&TElementContainerNode&TProjectionNode& TContainerNode&TElementContainerNode&TProjectionNode&TIcuContainerNode {
TIcuContainerNode {
const lView = getLView(); const lView = getLView();
const tView = lView[TVIEW]; const tView = lView[TVIEW];
const adjustedIndex = index + HEADER_OFFSET; const adjustedIndex = index + HEADER_OFFSET;
ngDevMode &&
assertLessThan(adjustedIndex, lView.length, `Slot should have been initialized with null`);
lView[adjustedIndex] = native;
const previousOrParentTNode = getPreviousOrParentTNode(); const previousOrParentTNode = getPreviousOrParentTNode();
let tNode = tView.data[adjustedIndex] as TNode; 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, lView[BINDING_INDEX], lView[TVIEW].bindingStartIndex,
'text nodes should be created before any bindings'); 'text nodes should be created before any bindings');
ngDevMode && ngDevMode.rendererCreateTextNode++; ngDevMode && ngDevMode.rendererCreateTextNode++;
const textNative = createTextNode(value, lView[RENDERER]); ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
const tNode = createNodeAtIndex(index, TNodeType.Element, textNative, null, null); const textNative = lView[index + HEADER_OFFSET] = createTextNode(value, lView[RENDERER]);
const tNode = createNodeAtIndex(index, TNodeType.Element, null, null);
// Text nodes are self closing. // Text nodes are self closing.
setIsNotParent(); setIsNotParent();

View File

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