refactor(core): view engine, refactor runtime data
Structure in a better way, in preparation for queries.
This commit is contained in:
parent
05b2b49711
commit
fc8694ed11
|
@ -97,7 +97,7 @@ export function elementDef(
|
|||
}
|
||||
|
||||
export function createElement(view: ViewData, renderHost: any, def: NodeDef): NodeData {
|
||||
const parentNode = def.parent != null ? view.nodes[def.parent].renderNode : renderHost;
|
||||
const parentNode = def.parent != null ? view.nodes[def.parent].elementOrText.node : renderHost;
|
||||
const elDef = def.element;
|
||||
let el: any;
|
||||
if (view.renderer) {
|
||||
|
@ -150,10 +150,10 @@ export function createElement(view: ViewData, renderHost: any, def: NodeDef): No
|
|||
}
|
||||
}
|
||||
return {
|
||||
renderNode: el,
|
||||
elementOrText:
|
||||
{node: el, embeddedViews: (def.flags & NodeFlags.HasEmbeddedViews) ? [] : undefined},
|
||||
provider: undefined,
|
||||
embeddedViews: (def.flags & NodeFlags.HasEmbeddedViews) ? [] : undefined,
|
||||
componentView: undefined
|
||||
pureExpression: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -213,7 +213,7 @@ function checkAndUpdateElementValue(view: ViewData, def: NodeDef, bindingIdx: nu
|
|||
|
||||
const binding = def.bindings[bindingIdx];
|
||||
const name = binding.name;
|
||||
const renderNode = view.nodes[def.index].renderNode;
|
||||
const renderNode = view.nodes[def.index].elementOrText.node;
|
||||
switch (binding.type) {
|
||||
case BindingType.ElementAttribute:
|
||||
setElementAttribute(view, binding, renderNode, name, value);
|
||||
|
|
|
@ -102,16 +102,16 @@ export function createProvider(view: ViewData, def: NodeDef, componentView: View
|
|||
}
|
||||
}
|
||||
return {
|
||||
renderNode: undefined,
|
||||
provider,
|
||||
embeddedViews: undefined, componentView,
|
||||
elementOrText: undefined,
|
||||
provider: {instance: provider, componentView: componentView},
|
||||
pureExpression: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function checkAndUpdateProviderInline(
|
||||
view: ViewData, def: NodeDef, v0: any, v1: any, v2: any, v3: any, v4: any, v5: any, v6: any,
|
||||
v7: any, v8: any, v9: any) {
|
||||
const provider = view.nodes[def.index].provider;
|
||||
const provider = view.nodes[def.index].provider.instance;
|
||||
let changes: SimpleChanges;
|
||||
// Note: fallthrough is intended!
|
||||
switch (def.bindings.length) {
|
||||
|
@ -148,7 +148,7 @@ export function checkAndUpdateProviderInline(
|
|||
}
|
||||
|
||||
export function checkAndUpdateProviderDynamic(view: ViewData, def: NodeDef, values: any[]) {
|
||||
const provider = view.nodes[def.index].provider;
|
||||
const provider = view.nodes[def.index].provider.instance;
|
||||
let changes: SimpleChanges;
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
changes = checkAndUpdateProp(view, provider, def, i, values[i], changes);
|
||||
|
@ -217,7 +217,7 @@ export function resolveDep(
|
|||
return Injector.NULL.get(depDef.token, notFoundValue);
|
||||
}
|
||||
case ElementRefTokenKey:
|
||||
return new ElementRef(view.nodes[elIndex].renderNode);
|
||||
return new ElementRef(view.nodes[elIndex].elementOrText.node);
|
||||
case ViewContainerRefTokenKey:
|
||||
return view.services.createViewContainerRef(view.nodes[elIndex]);
|
||||
case TemplateRefTokenKey:
|
||||
|
@ -225,7 +225,7 @@ export function resolveDep(
|
|||
default:
|
||||
const providerIndex = elDef.providerIndices[tokenKey];
|
||||
if (providerIndex != null) {
|
||||
return view.nodes[providerIndex].provider;
|
||||
return view.nodes[providerIndex].provider.instance;
|
||||
}
|
||||
}
|
||||
elIndex = view.parentIndex;
|
||||
|
@ -255,7 +255,7 @@ function checkAndUpdateProp(
|
|||
|
||||
if (view.def.flags & ViewFlags.LogBindingUpdate) {
|
||||
setBindingDebugInfo(
|
||||
view.renderer, view.nodes[def.parent].renderNode, binding.nonMinifiedName, value);
|
||||
view.renderer, view.nodes[def.parent].elementOrText.node, binding.nonMinifiedName, value);
|
||||
}
|
||||
if (change) {
|
||||
changes = changes || {};
|
||||
|
@ -276,7 +276,7 @@ export function callLifecycleHooksChildrenFirst(view: ViewData, lifecycles: Node
|
|||
const nodeIndex = nodeDef.index;
|
||||
if (nodeDef.flags & lifecycles) {
|
||||
// a leaf
|
||||
callProviderLifecycles(view.nodes[nodeIndex].provider, nodeDef.flags & lifecycles);
|
||||
callProviderLifecycles(view.nodes[nodeIndex].provider.instance, nodeDef.flags & lifecycles);
|
||||
} else if ((nodeDef.childFlags & lifecycles) === 0) {
|
||||
// a parent with leafs
|
||||
// no child matches one of the lifecycles,
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import {resolveDep, tokenKey} from './provider';
|
||||
import {BindingDef, BindingType, DepDef, DepFlags, NodeData, NodeDef, NodeType, PureExpressionData, PureExpressionType, ViewData} from './types';
|
||||
import {BindingDef, BindingType, DepDef, DepFlags, NodeData, NodeDef, NodeType, ProviderData, PureExpressionType, ViewData} from './types';
|
||||
import {checkAndUpdateBinding} from './util';
|
||||
|
||||
export function purePipeDef(pipeToken: any, argCount: number): NodeDef {
|
||||
|
@ -62,13 +62,7 @@ export function createPureExpression(view: ViewData, def: NodeDef): NodeData {
|
|||
const pipe = def.pureExpression.pipeDep ?
|
||||
resolveDep(view, def.parent, def.pureExpression.pipeDep) :
|
||||
undefined;
|
||||
const data: PureExpressionData = {value: undefined, pipe: pipe};
|
||||
return {
|
||||
renderNode: undefined,
|
||||
provider: data,
|
||||
embeddedViews: undefined,
|
||||
componentView: undefined
|
||||
};
|
||||
return {elementOrText: undefined, provider: undefined, pureExpression: {value: undefined, pipe}};
|
||||
}
|
||||
|
||||
export function checkAndUpdatePureExpressionInline(
|
||||
|
@ -101,7 +95,7 @@ export function checkAndUpdatePureExpressionInline(
|
|||
}
|
||||
|
||||
if (changed) {
|
||||
const data: PureExpressionData = view.nodes[def.index].provider;
|
||||
const data = view.nodes[def.index].pureExpression;
|
||||
let value: any;
|
||||
switch (def.pureExpression.type) {
|
||||
case PureExpressionType.Array:
|
||||
|
@ -206,7 +200,7 @@ export function checkAndUpdatePureExpressionDynamic(view: ViewData, def: NodeDef
|
|||
}
|
||||
}
|
||||
if (changed) {
|
||||
const data: PureExpressionData = view.nodes[def.index].provider;
|
||||
const data = view.nodes[def.index].pureExpression;
|
||||
let value: any;
|
||||
switch (def.pureExpression.type) {
|
||||
case PureExpressionType.Array:
|
||||
|
|
|
@ -48,16 +48,18 @@ class ViewContainerRef_ implements ViewContainerRef {
|
|||
get parentInjector(): Injector { return <Injector>unimplemented(); }
|
||||
|
||||
clear(): void {
|
||||
const len = this._data.embeddedViews.length;
|
||||
const len = this._data.elementOrText.embeddedViews.length;
|
||||
for (let i = len - 1; i >= 0; i--) {
|
||||
const view = detachEmbeddedView(this._data, i);
|
||||
destroyView(view);
|
||||
}
|
||||
}
|
||||
|
||||
get(index: number): ViewRef { return new ViewRef_(this._data.embeddedViews[index]); }
|
||||
get(index: number): ViewRef {
|
||||
return new ViewRef_(this._data.elementOrText.embeddedViews[index]);
|
||||
}
|
||||
|
||||
get length(): number { return this._data.embeddedViews.length; };
|
||||
get length(): number { return this._data.elementOrText.embeddedViews.length; };
|
||||
|
||||
createEmbeddedView<C>(templateRef: TemplateRef<C>, context?: C, index?: number):
|
||||
EmbeddedViewRef<C> {
|
||||
|
@ -81,7 +83,7 @@ class ViewContainerRef_ implements ViewContainerRef {
|
|||
move(viewRef: ViewRef, currentIndex: number): ViewRef { return unimplemented(); }
|
||||
|
||||
indexOf(viewRef: ViewRef): number {
|
||||
return this._data.embeddedViews.indexOf((<ViewRef_>viewRef)._view);
|
||||
return this._data.elementOrText.embeddedViews.indexOf((<ViewRef_>viewRef)._view);
|
||||
}
|
||||
|
||||
remove(index?: number): void {
|
||||
|
@ -126,6 +128,6 @@ class TemplateRef_ implements TemplateRef<any> {
|
|||
}
|
||||
|
||||
get elementRef(): ElementRef {
|
||||
return new ElementRef(this._parentView.nodes[this._def.index].renderNode);
|
||||
return new ElementRef(this._parentView.nodes[this._def.index].elementOrText.node);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ export function textDef(constants: string[]): NodeDef {
|
|||
}
|
||||
|
||||
export function createText(view: ViewData, renderHost: any, def: NodeDef): NodeData {
|
||||
const parentNode = def.parent != null ? view.nodes[def.parent].renderNode : renderHost;
|
||||
const parentNode = def.parent != null ? view.nodes[def.parent].elementOrText.node : renderHost;
|
||||
let renderNode: any;
|
||||
if (view.renderer) {
|
||||
renderNode = view.renderer.createText(parentNode, def.text.prefix);
|
||||
|
@ -54,7 +54,11 @@ export function createText(view: ViewData, renderHost: any, def: NodeDef): NodeD
|
|||
parentNode.appendChild(renderNode);
|
||||
}
|
||||
}
|
||||
return {renderNode, provider: undefined, embeddedViews: undefined, componentView: undefined};
|
||||
return {
|
||||
elementOrText: {node: renderNode, embeddedViews: undefined},
|
||||
provider: undefined,
|
||||
pureExpression: undefined
|
||||
};
|
||||
}
|
||||
|
||||
export function checkAndUpdateTextInline(
|
||||
|
@ -112,7 +116,7 @@ export function checkAndUpdateTextInline(
|
|||
value = _addInterpolationPart(v0, bindings[0]) + value;
|
||||
}
|
||||
value = def.text.prefix + value;
|
||||
const renderNode = view.nodes[def.index].renderNode;
|
||||
const renderNode = view.nodes[def.index].elementOrText.node;
|
||||
if (view.renderer) {
|
||||
view.renderer.setText(renderNode, value);
|
||||
} else {
|
||||
|
@ -137,7 +141,7 @@ export function checkAndUpdateTextDynamic(view: ViewData, def: NodeDef, values:
|
|||
value = value + _addInterpolationPart(values[i], bindings[i]);
|
||||
}
|
||||
value = def.text.prefix + value;
|
||||
const renderNode = view.nodes[def.index].renderNode;
|
||||
const renderNode = view.nodes[def.index].elementOrText.node;
|
||||
if (view.renderer) {
|
||||
view.renderer.setText(renderNode, value);
|
||||
} else {
|
||||
|
|
|
@ -206,12 +206,21 @@ export type DisposableFn = () => void;
|
|||
* Attention: Adding fields to this is performance sensitive!
|
||||
*/
|
||||
export interface NodeData {
|
||||
renderNode: any;
|
||||
provider: PureExpressionData|any;
|
||||
componentView: ViewData;
|
||||
elementOrText: ElementOrTextData;
|
||||
provider: ProviderData;
|
||||
pureExpression: PureExpressionData;
|
||||
}
|
||||
|
||||
export interface ElementOrTextData {
|
||||
node: any;
|
||||
embeddedViews: ViewData[];
|
||||
}
|
||||
|
||||
export interface ProviderData {
|
||||
instance: any;
|
||||
componentView: ViewData;
|
||||
}
|
||||
|
||||
export interface PureExpressionData {
|
||||
value: any;
|
||||
pipe: PipeTransform;
|
||||
|
|
|
@ -13,7 +13,7 @@ import {checkAndUpdateElementDynamic, checkAndUpdateElementInline, createElement
|
|||
import {callLifecycleHooksChildrenFirst, checkAndUpdateProviderDynamic, checkAndUpdateProviderInline, createProvider} from './provider';
|
||||
import {checkAndUpdatePureExpressionDynamic, checkAndUpdatePureExpressionInline, createPureExpression} from './pure_expression';
|
||||
import {checkAndUpdateTextDynamic, checkAndUpdateTextInline, createText} from './text';
|
||||
import {ElementDef, NodeData, NodeDef, NodeFlags, NodeType, NodeUpdater, ProviderDef, PureExpressionData, Services, TextDef, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn} from './types';
|
||||
import {ElementDef, NodeData, NodeDef, NodeFlags, NodeType, NodeUpdater, ProviderData, ProviderDef, Services, TextDef, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn} from './types';
|
||||
import {checkBindingNoChanges} from './util';
|
||||
|
||||
const NOOP = (): any => undefined;
|
||||
|
@ -274,8 +274,7 @@ const CheckNoChanges: NodeUpdater = {
|
|||
checkBindingNoChanges(view, nodeDef, 0, v0);
|
||||
}
|
||||
if (nodeDef.type === NodeType.PureExpression) {
|
||||
const data: PureExpressionData = view.nodes[index].provider;
|
||||
return data.value;
|
||||
return view.nodes[index].pureExpression.value;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
@ -285,8 +284,7 @@ const CheckNoChanges: NodeUpdater = {
|
|||
checkBindingNoChanges(view, nodeDef, i, values[i]);
|
||||
}
|
||||
if (nodeDef.type === NodeType.PureExpression) {
|
||||
const data: PureExpressionData = view.nodes[index].provider;
|
||||
return data.value;
|
||||
return view.nodes[index].pureExpression.value;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
@ -321,8 +319,7 @@ const CheckAndUpdate: NodeUpdater = {
|
|||
return undefined;
|
||||
case NodeType.PureExpression:
|
||||
checkAndUpdatePureExpressionInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
|
||||
const data: PureExpressionData = view.nodes[index].provider;
|
||||
return data.value;
|
||||
return view.nodes[index].pureExpression.value;
|
||||
}
|
||||
},
|
||||
checkDynamic: (view: ViewData, index: number, values: any[]): void => {
|
||||
|
@ -339,8 +336,7 @@ const CheckAndUpdate: NodeUpdater = {
|
|||
return undefined;
|
||||
case NodeType.PureExpression:
|
||||
checkAndUpdatePureExpressionDynamic(view, nodeDef, values);
|
||||
const data: PureExpressionData = view.nodes[index].provider;
|
||||
return data.value;
|
||||
return view.nodes[index].pureExpression.value;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -374,13 +370,15 @@ function execComponentViewsAction(view: ViewData, action: ViewAction) {
|
|||
// a leaf
|
||||
const nodeData = view.nodes[i];
|
||||
if (action === ViewAction.InitComponent) {
|
||||
let renderHost = view.nodes[nodeDef.parent].renderNode;
|
||||
let renderHost = view.nodes[nodeDef.parent].elementOrText.node;
|
||||
if (view.renderer) {
|
||||
renderHost = view.renderer.createViewRoot(renderHost);
|
||||
}
|
||||
initView(nodeData.componentView, renderHost, nodeData.provider, nodeData.provider);
|
||||
initView(
|
||||
nodeData.provider.componentView, renderHost, nodeData.provider.instance,
|
||||
nodeData.provider.instance);
|
||||
} else {
|
||||
callViewAction(nodeData.componentView, action);
|
||||
callViewAction(nodeData.provider.componentView, action);
|
||||
}
|
||||
} else if ((nodeDef.childFlags & NodeFlags.HasComponent) === 0) {
|
||||
// a parent with leafs
|
||||
|
@ -401,7 +399,7 @@ function execEmbeddedViewsAction(view: ViewData, action: ViewAction) {
|
|||
if (nodeDef.flags & NodeFlags.HasEmbeddedViews) {
|
||||
// a leaf
|
||||
const nodeData = view.nodes[i];
|
||||
const embeddedViews = nodeData.embeddedViews;
|
||||
const embeddedViews = nodeData.elementOrText.embeddedViews;
|
||||
if (embeddedViews) {
|
||||
for (let k = 0; k < embeddedViews.length; k++) {
|
||||
callViewAction(embeddedViews[k], action);
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import {NodeData, NodeFlags, ViewData} from './types';
|
||||
|
||||
export function attachEmbeddedView(node: NodeData, viewIndex: number, view: ViewData) {
|
||||
let embeddedViews = node.embeddedViews;
|
||||
let embeddedViews = node.elementOrText.embeddedViews;
|
||||
if (viewIndex == null) {
|
||||
viewIndex = embeddedViews.length;
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ export function attachEmbeddedView(node: NodeData, viewIndex: number, view: View
|
|||
}
|
||||
const prevView = viewIndex > 0 ? embeddedViews[viewIndex - 1] : null;
|
||||
const prevNode = prevView ? prevView.nodes[prevView.def.lastRootNode] : node;
|
||||
const prevRenderNode = prevNode.renderNode;
|
||||
const prevRenderNode = prevNode.elementOrText.node;
|
||||
if (view.renderer) {
|
||||
view.renderer.attachViewAfter(prevRenderNode, rootRenderNodes(view));
|
||||
} else {
|
||||
|
@ -35,7 +35,8 @@ export function attachEmbeddedView(node: NodeData, viewIndex: number, view: View
|
|||
}
|
||||
|
||||
export function detachEmbeddedView(node: NodeData, viewIndex: number): ViewData {
|
||||
const embeddedViews = node.embeddedViews;
|
||||
const renderData = node.elementOrText;
|
||||
const embeddedViews = renderData.embeddedViews;
|
||||
if (viewIndex == null) {
|
||||
viewIndex = embeddedViews.length;
|
||||
}
|
||||
|
@ -49,7 +50,7 @@ export function detachEmbeddedView(node: NodeData, viewIndex: number): ViewData
|
|||
if (view.renderer) {
|
||||
view.renderer.detachView(rootRenderNodes(view));
|
||||
} else {
|
||||
const parentNode = node.renderNode.parentNode;
|
||||
const parentNode = renderData.node.parentNode;
|
||||
if (parentNode) {
|
||||
directDomAttachDetachSiblingRenderNodes(
|
||||
view, 0, DirectDomAction.RemoveChild, parentNode, null);
|
||||
|
@ -67,8 +68,8 @@ export function rootRenderNodes(view: ViewData): any[] {
|
|||
function collectSiblingRenderNodes(view: ViewData, startIndex: number, target: any[]) {
|
||||
for (let i = startIndex; i < view.nodes.length; i++) {
|
||||
const nodeDef = view.def.nodes[i];
|
||||
const nodeData = view.nodes[i];
|
||||
target.push(nodeData.renderNode);
|
||||
const nodeData = view.nodes[i].elementOrText;
|
||||
target.push(nodeData.node);
|
||||
if (nodeDef.flags & NodeFlags.HasEmbeddedViews) {
|
||||
const embeddedViews = nodeData.embeddedViews;
|
||||
if (embeddedViews) {
|
||||
|
@ -93,16 +94,16 @@ function directDomAttachDetachSiblingRenderNodes(
|
|||
nextSibling: any) {
|
||||
for (let i = startIndex; i < view.nodes.length; i++) {
|
||||
const nodeDef = view.def.nodes[i];
|
||||
const nodeData = view.nodes[i];
|
||||
const nodeData = view.nodes[i].elementOrText;
|
||||
switch (action) {
|
||||
case DirectDomAction.AppendChild:
|
||||
parentNode.appendChild(nodeData.renderNode);
|
||||
parentNode.appendChild(nodeData.node);
|
||||
break;
|
||||
case DirectDomAction.InsertBefore:
|
||||
parentNode.insertBefore(nodeData.renderNode, nextSibling);
|
||||
parentNode.insertBefore(nodeData.node, nextSibling);
|
||||
break;
|
||||
case DirectDomAction.RemoveChild:
|
||||
parentNode.removeChild(nodeData.renderNode);
|
||||
parentNode.removeChild(nodeData.node);
|
||||
break;
|
||||
}
|
||||
if (nodeDef.flags & NodeFlags.HasEmbeddedViews) {
|
||||
|
|
|
@ -58,7 +58,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) {
|
|||
])),
|
||||
]));
|
||||
|
||||
const compView = view.nodes[1].componentView;
|
||||
const compView = view.nodes[1].provider.componentView;
|
||||
|
||||
expect(compView.context).toBe(instance);
|
||||
expect(compView.component).toBe(instance);
|
||||
|
@ -85,7 +85,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) {
|
|||
], update
|
||||
)),
|
||||
], jasmine.createSpy('parentUpdater')));
|
||||
const compView = view.nodes[1].componentView;
|
||||
const compView = view.nodes[1].provider.componentView;
|
||||
|
||||
checkAndUpdateView(view);
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ export function main() {
|
|||
updater, inlineDynamic, view, 2,
|
||||
[callUpdater(updater, inlineDynamic, view, 1, values)]);
|
||||
}));
|
||||
const service = view.nodes[2].provider;
|
||||
const service = view.nodes[2].provider.instance;
|
||||
|
||||
values = [1, 2];
|
||||
checkAndUpdateView(view);
|
||||
|
@ -87,7 +87,7 @@ export function main() {
|
|||
updater, inlineDynamic, view, 2,
|
||||
[callUpdater(updater, inlineDynamic, view, 1, values)]);
|
||||
}));
|
||||
const service = view.nodes[2].provider;
|
||||
const service = view.nodes[2].provider.instance;
|
||||
|
||||
values = [1, 2];
|
||||
checkAndUpdateView(view);
|
||||
|
@ -126,7 +126,7 @@ export function main() {
|
|||
updater, inlineDynamic, view, 3,
|
||||
[callUpdater(updater, inlineDynamic, view, 2, values)]);
|
||||
}));
|
||||
const service = view.nodes[3].provider;
|
||||
const service = view.nodes[3].provider.instance;
|
||||
|
||||
values = [1, 2];
|
||||
checkAndUpdateView(view);
|
||||
|
|
|
@ -84,8 +84,8 @@ export class AppModule {
|
|||
}
|
||||
bootstrap() {
|
||||
this.rootView = createRootView(new DefaultServices(null, this.sanitizer), TreeComponent_Host);
|
||||
this.rootComp = this.rootView.nodes[1].provider;
|
||||
this.rootEl = this.rootView.nodes[0].renderNode;
|
||||
this.rootComp = this.rootView.nodes[1].provider.instance;
|
||||
this.rootEl = this.rootView.nodes[0].elementOrText.node;
|
||||
}
|
||||
tick() { checkAndUpdateView(this.rootView); }
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue