[IMP] component: refactor rendering pipeline

This commit introduces a brand new rendering system based on a fiber
class and a scheduler.

closes #330
This commit is contained in:
Aaron Bohy
2019-10-25 15:45:56 +02:00
committed by Géry Debongnie
parent 2bed1cfbd1
commit 9c5cad15c1
24 changed files with 2296 additions and 1320 deletions
File diff suppressed because it is too large Load Diff
@@ -1,9 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`default props default values are also set whenever component is updated 1`] = `"<div>1</div>"`;
exports[`default props default values are also set whenever component is updated 2`] = `"<div>4</div>"`;
exports[`props validation props are validated in dev mode (code snapshot) 1`] = `
"function anonymous(context,extra
) {
@@ -11,38 +7,38 @@ exports[`props validation props are validated in dev mode (code snapshot) 1`] =
let QWeb = this.constructor;
let parent = context;
let owner = context;
let sibling = null;
var h = this.h;
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
//COMPONENT
let def3;
let templateId4 = \`__5__\`;
let w4 = templateId4 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId4]] : false;
let _2_index = c1.length;
c1.push(null);
let props4 = {message:1};
if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) {
if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) {
def3 = w4.__owl__.currentFiber.promise;
} else {
w4.destroy();
w4 = false;
}
let def2;
let templateId3 = \`__4__\`;
let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false;
let props3 = {message:1};
if (w3 && w3.__owl__.currentFiber && !w3.__owl__.vnode) {
w3.destroy();
w3 = false;
}
if (!w4) {
let componentKey4 = \`Child\`;
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4]|| context['Child'];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[templateId4] = w4.__owl__.id;
def3 = w4.__prepare(extra.fiber, undefined, undefined);
def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: templateId4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;});
if (!w3) {
let componentKey3 = \`Child\`;
let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['Child'];
if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')}
w3 = new W3(parent, props3);
parent.__owl__.cmap[templateId3] = w3.__owl__.id;
def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling);
let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}});
const fiber = w3.__owl__.currentFiber;
def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; });
c1.push(pvnode);
w3.__owl__.pvnode = pvnode;
} else {
utils.validateProps(w4.constructor, props4)
def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined);
def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;});
utils.validateProps(w3.constructor, props3)
def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling);
let pvnode = w3.__owl__.pvnode;
c1.push(pvnode);
}
extra.promises.push(def3);
sibling = w3.__owl__.currentFiber;
return vn1;
}"
`;
File diff suppressed because it is too large Load Diff
+14 -12
View File
@@ -1,5 +1,6 @@
import { Component, Env } from "../../src/component/component";
import { makeTestFixture, makeTestEnv } from "../helpers";
import { makeTestFixture, makeTestEnv, nextTick } from "../helpers";
import { useState } from "../../src/hooks";
import { QWeb } from "../../src/qweb";
import { xml } from "../../src/tags";
@@ -336,21 +337,22 @@ describe("default props", () => {
test("default values are also set whenever component is updated", async () => {
class TestWidget extends Widget {
static template = xml`<div><t t-esc="props.p"/></div>`;
static defaultProps = { p: 4 };
}
env.qweb.addTemplates(`
<templates>
<div t-name="TestWidget"><t t-esc="props.p"/></div>
</templates>`);
class Parent extends Widget {
static template = xml`<div><TestWidget p="state.p"/></div>`;
static components = { TestWidget };
state: any = useState({ p: 1 });
}
const w = new TestWidget(env, { p: 1 });
const w = new Parent(env);
await w.mount(fixture);
expect(fixture.innerHTML).toMatchSnapshot();
const fiber = w.__createFiber(false, undefined, undefined, undefined);
await w.__updateProps({}, fiber);
await w.render();
expect(w.props.p).toBe(4);
expect(fixture.innerHTML).toMatchSnapshot();
expect(fixture.innerHTML).toBe("<div><div>1</div></div>");
w.state.p = undefined;
await nextTick();
expect(fixture.innerHTML).toBe("<div><div>4</div></div>");
});
test("can set default required boolean values", async () => {