Skip to content
This repository has been archived by the owner on Jul 30, 2018. It is now read-only.

Integrate VDOM system into widget-core #728

Merged
merged 62 commits into from
Oct 26, 2017
Merged

Integrate VDOM system into widget-core #728

merged 62 commits into from
Oct 26, 2017

Conversation

agubler
Copy link
Member

@agubler agubler commented Oct 20, 2017

Type: feature

The following has been addressed in the PR:

  • There is a related issue
  • All code matches the style guide
  • Unit or Functional tests are included in the PR

Description:

Integrates a fork of Maquette into widget-core that has been converted to deal with the widget-core DNode abstraction. All widget instance management has been moved from WidgetBase into the vdom functionality.

Achieves at least feature and performance parity with the existing implementation.

Includes updated variable names and code styling but maintains large amounts of the existing architecture and logic from Maquette which will be improved on over time.

Performance Benchmark Comparison between 0.1.2 (current) and 0.2.0 (new vdom)

interactive_results

Using js-framework-benchmark

Resolves #725

src/vdom.ts Outdated
filterAndDecorateChildren(child.children, instance);
}
}
} else {
Copy link
Member Author

Choose a reason for hiding this comment

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

formatting

…meout when requestIdleCallback isn't supported
@dylans dylans added this to the 2017.10 milestone Oct 20, 2017
Copy link
Member

@kitsonk kitsonk left a comment

Choose a reason for hiding this comment

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

A couple comments, overall it looks good.

@@ -156,6 +124,20 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> extends E
this.own(this._nodeHandler);
this._boundRenderFunc = this.render.bind(this);
this._boundInvalidate = this.invalidate.bind(this);
this.own(this.on('element-created', ({ key, element }: any) => {
Copy link
Member

Choose a reason for hiding this comment

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

you can use a map here, which returns a single composite handle:

this.on({
  'element-create'({ key, element }: any) { /* ... */ },
  'eleement-updated'({ key, element: any) { /* ... */ },
  ...
});

Also it seems like the any could/should be more specific?

Copy link
Member Author

Choose a reason for hiding this comment

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

Nice I'll give that a try, also add the proper typings over any.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated

}

protected invalidate(): void {
public invalidate(): void {
Copy link
Member

Choose a reason for hiding this comment

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

why the change is visibility?

Copy link
Member Author

Choose a reason for hiding this comment

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

It now get's called from outside of the widget instance (in vdom), previously it was called from within the instance in dNodeToVNode

Copy link
Member

Choose a reason for hiding this comment

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

👍

src/d.ts Outdated
if (typeof classes === 'function') {
classes = classes();
properties = assign(properties, { classes });
if (properties) {
Copy link
Member

Choose a reason for hiding this comment

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

Not sure I can see how properties could be undefined here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup, I think could possibly remove that (it's because at one point I allowed undefined properties and changed my mind) - but there is a change following these that will remove this entire section so perhaps wait for that. I don't mind.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated

import { v } from './../d';
import { VNode } from '@dojo/interfaces/vdom';
import { InternalHNode } from './../vdom';
Copy link
Member

Choose a reason for hiding this comment

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

We probably need to get rid of VNode in interfaces after we land this, right? It is used in a couple places (like test-extras) which sort of had to deal with maquette nodes directly.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup we can remove them afterwards for sure and yup test-extras is going to suffer the most from these changes. Otherwise updating widgets was just a matter of swapping VNodes for DNodes

@@ -29,6 +29,12 @@ global.requestAnimationFrame = (cb: (...args: any[]) => {}) => {
return true;
};

global.requestIdleCallback = (cb: (...args: any[]) => {}) => {
Copy link
Member

Choose a reason for hiding this comment

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

reminder that we would want to address this in https://github.com/dojo/test-extras/blob/master/src/support/loadJsdom.ts as well

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup! Thanks!

Copy link
Member

@kitsonk kitsonk left a comment

Choose a reason for hiding this comment

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

Looks good.

Copy link
Member

@tomdye tomdye left a comment

Choose a reason for hiding this comment

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

Just the one question re. resolvers being called twice.

@@ -54,7 +46,8 @@ registerSuite({
const widget = new TestWidget();
widget.append(div);

resolveRAF();
resolvers.resolve();
Copy link
Member

Choose a reason for hiding this comment

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

why are you calling this twice here and only once elsewhere? It was only called once before.

Copy link
Member Author

Choose a reason for hiding this comment

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

@tomdye this is because after the render we need to resolve the requestIdleCallbacks, which with meta can cause an invalidation. So means we need to resolve the requestAnimationFrame (and idle callbacks again) to reflect the outcome from the render.

@kitsonk
Copy link
Member

kitsonk commented Oct 26, 2017

@agubler there is a regression from maquettes behaviour. Previously v('div.foo') resulted in a HTMLDivElement with classes of foo, now it results in an HTMLUnknownElement with a tagName of DIV.FOO. I suspect other things like ID selectors (div#bar) in the string also exhibit that behaviour.

@agubler
Copy link
Member Author

agubler commented Oct 26, 2017

@kitsonk that’s correct, removing the support for ids and classes to be able to be passed as part of the selector was a conceous decision (the code logic was complicated and is pretty much considered an anti-pattern within Dojo 2).

It’s one of the few areas where the behaviour between the two implementations differ (on purpose!).

@kitsonk
Copy link
Member

kitsonk commented Oct 26, 2017

@agubler is it worth throwing then on strings that contain anything but /[a-zA-Z0-9\-]+/? That would cover all HTML defined tags and only valid custom element tags. I had a few test cases lying about using that behaviour, and while I would expect it being a minority, anyone familiar with HyperScript might assume it is supported.

@agubler
Copy link
Member Author

agubler commented Oct 26, 2017

@kitsonk I'm not sure there would be too much value, it would only prevent using . and # as part of the tag (that has never been supported when using v()). You could still pass an incorrect HTML element tag name and also it would be a hot path.

If it becomes an issue with consumers we can possibly look to address it later?

@kitsonk
Copy link
Member

kitsonk commented Oct 26, 2017

that has never been supported when using v()

Well, it wasn't supported because those were broken out and applied to the DOM node.

If it becomes an issue with consumers we can possibly look to address it later?

Yeah, fine.

@agubler agubler merged commit 7dbf15f into dojo:master Oct 26, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants