mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aef6923c23 |
@@ -120,20 +120,30 @@ export class ComponentNode<P = any, E = any> implements VNode<ComponentNode<P, E
|
|||||||
this.initiateRender(fiber);
|
this.initiateRender(fiber);
|
||||||
}
|
}
|
||||||
|
|
||||||
async initiateRender(fiber: Fiber | MountFiber) {
|
initiateRender(fiber: Fiber | MountFiber) {
|
||||||
this.fiber = fiber;
|
this.fiber = fiber;
|
||||||
if (this.mounted.length) {
|
if (this.mounted.length) {
|
||||||
fiber.root!.mounted.push(fiber);
|
fiber.root!.mounted.push(fiber);
|
||||||
}
|
}
|
||||||
const component = this.component;
|
const component = this.component;
|
||||||
|
const finish = () => {
|
||||||
|
if (this.status === STATUS.NEW && this.fiber === fiber) {
|
||||||
|
this._render(fiber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let willStartResults;
|
||||||
try {
|
try {
|
||||||
await Promise.all(this.willStart.map((f) => f.call(component)));
|
willStartResults = this.willStart.map((f) => f.call(component));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
handleError({ node: this, error: e });
|
handleError({ node: this, error: e });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.status === STATUS.NEW && this.fiber === fiber) {
|
if (willStartResults.some(result => result instanceof Promise)) {
|
||||||
this._render(fiber);
|
Promise.all(willStartResults)
|
||||||
|
.then(finish)
|
||||||
|
.catch(e => handleError({ node: this, error: e }));
|
||||||
|
} else {
|
||||||
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,25 +163,27 @@ export class ComponentNode<P = any, E = any> implements VNode<ComponentNode<P, E
|
|||||||
|
|
||||||
const fiber = makeRootFiber(this);
|
const fiber = makeRootFiber(this);
|
||||||
this.fiber = fiber;
|
this.fiber = fiber;
|
||||||
|
debugger;
|
||||||
|
window.requestAnimationFrame(() => {
|
||||||
|
if (this.status === STATUS.DESTROYED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// We only want to actually render the component if the following two
|
||||||
|
// conditions are true:
|
||||||
|
// * this.fiber: it could be null, in which case the render has been cancelled
|
||||||
|
// * (current || !fiber.parent): if current is not null, this means that the
|
||||||
|
// render function was called when a render was already occurring. In this
|
||||||
|
// case, the pending rendering was cancelled, and the fiber needs to be
|
||||||
|
// rendered to complete the work. If current is null, we check that the
|
||||||
|
// fiber has no parent. If that is the case, the fiber was downgraded from
|
||||||
|
// a root fiber to a child fiber in the previous microtick, because it was
|
||||||
|
// embedded in a rendering coming from above, so the fiber will be rendered
|
||||||
|
// in the next microtick anyway, so we should not render it again.
|
||||||
|
if (this.fiber === fiber && (current || !fiber.parent)) {
|
||||||
|
this._render(fiber);
|
||||||
|
}
|
||||||
|
});
|
||||||
this.app.scheduler.addFiber(fiber);
|
this.app.scheduler.addFiber(fiber);
|
||||||
await Promise.resolve();
|
|
||||||
if (this.status === STATUS.DESTROYED) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// We only want to actually render the component if the following two
|
|
||||||
// conditions are true:
|
|
||||||
// * this.fiber: it could be null, in which case the render has been cancelled
|
|
||||||
// * (current || !fiber.parent): if current is not null, this means that the
|
|
||||||
// render function was called when a render was already occurring. In this
|
|
||||||
// case, the pending rendering was cancelled, and the fiber needs to be
|
|
||||||
// rendered to complete the work. If current is null, we check that the
|
|
||||||
// fiber has no parent. If that is the case, the fiber was downgraded from
|
|
||||||
// a root fiber to a child fiber in the previous microtick, because it was
|
|
||||||
// embedded in a rendering coming from above, so the fiber will be rendered
|
|
||||||
// in the next microtick anyway, so we should not render it again.
|
|
||||||
if (this.fiber === fiber && (current || !fiber.parent)) {
|
|
||||||
this._render(fiber);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_render(fiber: Fiber | RootFiber) {
|
_render(fiber: Fiber | RootFiber) {
|
||||||
@@ -207,25 +219,32 @@ export class ComponentNode<P = any, E = any> implements VNode<ComponentNode<P, E
|
|||||||
this.status = STATUS.DESTROYED;
|
this.status = STATUS.DESTROYED;
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateAndRender(props: any, parentFiber: Fiber) {
|
updateAndRender(props: any, parentFiber: Fiber) {
|
||||||
// update
|
// update
|
||||||
const fiber = makeChildFiber(this, parentFiber);
|
const fiber = makeChildFiber(this, parentFiber);
|
||||||
this.fiber = fiber;
|
this.fiber = fiber;
|
||||||
const component = this.component;
|
const component = this.component;
|
||||||
applyDefaultProps(props, component.constructor as any);
|
applyDefaultProps(props, component.constructor as any);
|
||||||
const prom = Promise.all(this.willUpdateProps.map((f) => f.call(component, props)));
|
|
||||||
await prom;
|
const finish = () => {
|
||||||
if (fiber !== this.fiber) {
|
if (fiber !== this.fiber) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
component.props = props;
|
||||||
|
this._render(fiber);
|
||||||
|
const parentRoot = parentFiber.root!;
|
||||||
|
if (this.willPatch.length) {
|
||||||
|
parentRoot.willPatch.push(fiber);
|
||||||
|
}
|
||||||
|
if (this.patched.length) {
|
||||||
|
parentRoot.patched.push(fiber);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
component.props = props;
|
const willUpdatePropsResults = this.willUpdateProps.map((f) => f.call(component, props));
|
||||||
this._render(fiber);
|
if (willUpdatePropsResults.some(res => res instanceof Promise)) {
|
||||||
const parentRoot = parentFiber.root!;
|
Promise.all(willUpdatePropsResults).then(finish);
|
||||||
if (this.willPatch.length) {
|
} else {
|
||||||
parentRoot.willPatch.push(fiber);
|
finish();
|
||||||
}
|
|
||||||
if (this.patched.length) {
|
|
||||||
parentRoot.patched.push(fiber);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,17 +97,14 @@ test("destroying/recreating a subwidget with different props (if start is not ov
|
|||||||
expect(["W:setup", "W:willStart", "W:willRender", "W:rendered", "W:mounted"]).toBeLogged();
|
expect(["W:setup", "W:willStart", "W:willRender", "W:rendered", "W:mounted"]).toBeLogged();
|
||||||
|
|
||||||
expect(n).toBe(0);
|
expect(n).toBe(0);
|
||||||
|
|
||||||
w.state.val = 2;
|
w.state.val = 2;
|
||||||
await nextMicroTick();
|
await new Promise(requestAnimationFrame); // calls to _render are batched per animation frame
|
||||||
await nextMicroTick();
|
|
||||||
expect(n).toBe(1);
|
expect(n).toBe(1);
|
||||||
|
|
||||||
expect(["W:willRender", "Child:setup", "Child:willStart", "W:rendered"]).toBeLogged();
|
expect(["W:willRender", "Child:setup", "Child:willStart", "W:rendered"]).toBeLogged();
|
||||||
|
|
||||||
w.state.val = 3;
|
w.state.val = 3;
|
||||||
await nextMicroTick();
|
await new Promise(requestAnimationFrame);
|
||||||
await nextMicroTick();
|
|
||||||
expect(n).toBe(2);
|
expect(n).toBe(2);
|
||||||
|
|
||||||
expect([
|
expect([
|
||||||
|
|||||||
Reference in New Issue
Block a user