Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): add initial view engine #14014

Merged
merged 1 commit into from Jan 20, 2017
Merged

Conversation

tbosch
Copy link
Contributor

@tbosch tbosch commented Jan 19, 2017

The new view engine allows our codegen to produce less code,
as it can interpret view definitions during runtime.

The view engine is not feature complete yet, but already
allows to implement a tree benchmark based on it.

Part of #14013

@tbosch tbosch force-pushed the view_manager branch 3 times, most recently from bded18a to 0e4cee4 Compare January 19, 2017 18:44
@@ -8,7 +8,7 @@
"moduleResolution": "node",
"outDir": "../dist/all/",
"noImplicitAny": true,
"noFallthroughCasesInSwitch": true,
"noFallthroughCasesInSwitch": false,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this allowed in G3?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, for third party code.

providerDef(NodeFlags.None, TreeComponent, [], null, () => TreeComponent_0),
],
null,
new RenderComponentType('TreeComponent_Host', 'someUrl', 0, ViewEncapsulation.None, [], {}), );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we use directDom we don't need this here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

viewFlags,
[
elementDef(NodeFlags.None, 1, 'tree'),
providerDef(NodeFlags.None, TreeComponent, [], {'data': 0}, () => TreeComponent_0),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should not be quoted

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check the spec what happens with JavaScript keywords:

  • required quoting for an object literal vs allow to use via .x?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked in IE11 and Firefox, both allow var x = {function: 1} as well as x.function

NodeFlags.None, 1, 'span', null, [[BindingType.ElementStyle, 'backgroundColor', null]]),
textDef([' ', ' ']),
anchorDef(NodeFlags.HasEmbeddedViews, 1, TreeComponent_1),
providerDef(NodeFlags.None, NgIf, [ViewContainerRef, TemplateRef], {'ngIf': 0}),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't quote the properties

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

updater.checkInline(view, 3, cmp.data.left != null);
updater.checkInline(view, 5, cmp.data.right != null);
},
new RenderComponentType('TreeComponent_0', 'someUrl', 0, ViewEncapsulation.None, [], {}), );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove RendercomponentType in this example

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


export interface NodeUpdater {
checkInline(
view: ViewData, index: number, v0?: any, v1?: any, v2?: any, v3?: any, v4?: any, v5?: any,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nodeIndex

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


export interface TextDef { prefix: string; }

export interface NodeDef {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this up, think about order

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

export type ViewUpdateFn = (updater: NodeUpdater, view: ViewData, component: any, context: any) =>
void;

export interface ViewDefinition {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this up

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

void;

export interface ViewDefinition {
nodeFlags: NodeFlags;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comment: aggregation of flags of all nodes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

nodeFlags: NodeFlags;
flags: ViewFlags;
nodes: NodeDef[];
reverseChildNodes: NodeDef[];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comment

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment: providers are always after elements / anchors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

export interface ViewDefinition {
nodeFlags: NodeFlags;
flags: ViewFlags;
nodes: NodeDef[];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment: providers are always before elements / anchors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

bindingIndex: number;
bindings: BindingDef[];
element: ElementDef;
providerIndices: {[tokenKey: string]: number};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move into ProviderDef?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decided against it

embeddedViews: ViewData[];
}

export interface ViewData {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move up

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comment: performance sensitive (numbe rof properties)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

// Data
// -------------------------------------

export interface NodeData {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comment: performance sensitive (numbe rof properties)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

setElementAttribute(view, binding, renderNode, name, value);
break;
case BindingType.ElementClass:
if (view.renderer) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move into helpe ras well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

if (view.renderer) {
view.renderer.setElementAttribute(renderNode, name, renderValue);
} else {
renderNode.setAttribute(name, renderValue);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add code for atribute removal (see DomRenderer)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

if (view.renderer) {
view.renderer.setElementStyle(renderNode, name, renderValue);
} else {
renderNode.style[name] = renderValue;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check style removal?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

import {checkAndUpdateBinding, checkAndUpdateBindingWithChange, setBindingDebugInfo} from './util';

let _tokenKeyCache = new Map<any, string>();
let _nextTokenKeyIndex = 0;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove, use the size of the map

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

if (Array.isArray(value)) {
[flags, token] = value;
} else {
token = value;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flags = 0

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

return key;
}

export function resolveDep(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move to createIOnstance

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

view: ViewData, elIndex: number, depDef: DepDef,
notFoundValue: any = Injector.THROW_IF_NOT_FOUND): any {
const tokenKey = depDef.tokenKey;
let elDef = view.def.nodes[elIndex];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move into if below

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}

while (view) {
elDef = view.def.nodes[elIndex];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make const

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

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;
let changes: {[prop: string]: SimpleChange};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use SimpleChanges type

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

if (changes) {
provider.ngOnChanges(changes);
}
if ((def.flags & NodeFlags.OnInit) && view.firstChange) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move view.firstChange first

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

if (changes) {
provider.ngOnChanges(changes);
}
if ((def.flags & NodeFlags.OnInit) && view.firstChange) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move view.firstChagne first

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


function checkAndUpdateProp(
view: ViewData, provider: any, def: NodeDef, bindingIdx: number, value: any,
changes: {[propName: string]: SimpleChange}): {[propName: string]: SimpleChange} {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use SimpleChanges

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

i + nodesWithoutIndices[i].childCount - (currentParent.index + 1);
const parentEndIndexInReverseChildOrder =
currentParent.reverseChildIndex + currentParent.childCount;
reverseChildIndex =
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move outside of if

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

let componentView: ViewData;
if (nodeDef.component) {
const compViewDef = nodeDef.component();
const services = view.services;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inline

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}

const CheckAndUpdate: NodeUpdater = {
checkInline(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change to checkInline: (...)?!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

};

export function destroyView(view: ViewData) {
execComponentViewsAction(view, ViewAction.Destroy);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comment: Bottom up

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

export function destroyView(view: ViewData) {
execComponentViewsAction(view, ViewAction.Destroy);
execEmbeddedViewsAction(view, ViewAction.Destroy);
callLifecycleHooksChildrenFirst(view, NodeFlags.OnDestroy);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

call destroy before the views are destroyed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

const nextSibling = prevRenderNode.nextSibling;
if (parentNode) {
directDomAttachDetachSiblingRenderNodes(
view, 0, nextSibling ? DirectDomAction.InsertBefore : DirectDomAction.AppendChild,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move action into const before

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}
}
}
i += nodeDef.childCount;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add comment: This jumps to the next sibling

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}
}
}
i += nodeDef.childCount;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add comment: This jumps to the next sibling

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -0,0 +1,212 @@
/**
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

[BindingType.ElementAttribute, 'a2', SecurityContext.NONE]
]),
],
(updater, view) => updater.checkDynamic(view, 0, ['v1', 'v2'])));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactor these tests into 1 test or a generic test that just takes the updater as argument

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

expect(instance.b).toBe('v2');
});

it('should update via array', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fold into 1 test

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

});

describe('change text', () => {
it('should update inline', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merge into 1 test

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


export function main() {
describe('viewDef', () => {
describe('reverseChild oreder', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

it('should reverse child order for mixed levels', () => {
const vd = viewDef(ViewFlags.None, [
textDef(['a']), // level 0
elementDef(NodeFlags.None, 5, 'span'), // level 1
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

level 0, adjust others

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add indices to the comment

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor

@IgorMinar IgorMinar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add a comment to the tsconfig.json so that nobody copies that option. otherwise lgtm

@tbosch tbosch force-pushed the view_manager branch 2 times, most recently from 3861e93 to 4653203 Compare January 19, 2017 23:59
The new view engine allows our codegen to produce less code,
as it can interpret view definitions during runtime.

The view engine is not feature complete yet, but already
allows to implement a tree benchmark based on it.

Part of angular#14013
@tbosch tbosch added the action: merge The PR is ready for merge by the caretaker label Jan 20, 2017
@alxhub alxhub merged commit 2f87eb5 into angular:master Jan 20, 2017
@tbosch tbosch deleted the view_manager branch January 20, 2017 22:42
wKoza pushed a commit to wKoza/angular that referenced this pull request Feb 12, 2017
The new view engine allows our codegen to produce less code,
as it can interpret view definitions during runtime.

The view engine is not feature complete yet, but already
allows to implement a tree benchmark based on it.

Part of angular#14013
juleskremer pushed a commit to juleskremer/angular that referenced this pull request Aug 28, 2017
The new view engine allows our codegen to produce less code,
as it can interpret view definitions during runtime.

The view engine is not feature complete yet, but already
allows to implement a tree benchmark based on it.

Part of angular#14013
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 10, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants