mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
change children implementation, remove parented link on destroy
This commit is contained in:
@@ -23,7 +23,7 @@ interface Meta<T extends WEnv> {
|
|||||||
isMounted: boolean;
|
isMounted: boolean;
|
||||||
isDestroyed: boolean;
|
isDestroyed: boolean;
|
||||||
parent: Widget<T> | null;
|
parent: Widget<T> | null;
|
||||||
children: Widget<T>[];
|
children: { [key: number]: Widget<T> };
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Widget<T extends WEnv> {
|
export class Widget<T extends WEnv> {
|
||||||
@@ -45,22 +45,25 @@ export class Widget<T extends WEnv> {
|
|||||||
|
|
||||||
constructor(parent: Widget<T> | T, props?: any) {
|
constructor(parent: Widget<T> | T, props?: any) {
|
||||||
wl.push(this);
|
wl.push(this);
|
||||||
|
let id: number;
|
||||||
let p: Widget<T> | null = null;
|
let p: Widget<T> | null = null;
|
||||||
if (parent instanceof Widget) {
|
if (parent instanceof Widget) {
|
||||||
p = parent;
|
p = parent;
|
||||||
parent.__widget__.children.push(this);
|
|
||||||
this.env = parent.env;
|
this.env = parent.env;
|
||||||
|
id = this.env.getID();
|
||||||
|
parent.__widget__.children[id] = this;
|
||||||
} else {
|
} else {
|
||||||
this.env = parent;
|
this.env = parent;
|
||||||
|
id = this.env.getID();
|
||||||
}
|
}
|
||||||
this.__widget__ = {
|
this.__widget__ = {
|
||||||
id: this.env.getID(),
|
id: id,
|
||||||
vnode: null,
|
vnode: null,
|
||||||
isStarted: false,
|
isStarted: false,
|
||||||
isMounted: false,
|
isMounted: false,
|
||||||
isDestroyed: false,
|
isDestroyed: false,
|
||||||
parent: p,
|
parent: p,
|
||||||
children: []
|
children: {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,6 +100,11 @@ export class Widget<T extends WEnv> {
|
|||||||
this.el.remove();
|
this.el.remove();
|
||||||
delete this.__widget__.vnode;
|
delete this.__widget__.vnode;
|
||||||
}
|
}
|
||||||
|
if (this.__widget__.parent) {
|
||||||
|
let id = this.__widget__.id;
|
||||||
|
delete this.__widget__.parent.__widget__.children[id];
|
||||||
|
this.__widget__.parent = null;
|
||||||
|
}
|
||||||
this.__widget__.isDestroyed = true;
|
this.__widget__.isDestroyed = true;
|
||||||
this.destroyed();
|
this.destroyed();
|
||||||
}
|
}
|
||||||
@@ -163,8 +171,9 @@ export class Widget<T extends WEnv> {
|
|||||||
|
|
||||||
private visitSubTree(callback: (w: Widget<T>) => void) {
|
private visitSubTree(callback: (w: Widget<T>) => void) {
|
||||||
callback(this);
|
callback(this);
|
||||||
for (let child of this.__widget__.children) {
|
const children = this.__widget__.children;
|
||||||
child.visitSubTree(callback);
|
for (let id in children) {
|
||||||
|
children[id].visitSubTree(callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,12 @@ function nextTick(): Promise<void> {
|
|||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test widget
|
function children(w: Widget<WEnv>): Widget<WEnv>[] {
|
||||||
|
const childrenMap = w.__widget__.children;
|
||||||
|
return Object.keys(childrenMap).map(id => childrenMap[id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test widgets
|
||||||
class Counter extends Widget<WEnv> {
|
class Counter extends Widget<WEnv> {
|
||||||
name = "counter";
|
name = "counter";
|
||||||
template = `<div><t t-esc="state.counter"/><button t-on-click="inc">Inc</button></div>`;
|
template = `<div><t t-esc="state.counter"/><button t-on-click="inc">Inc</button></div>`;
|
||||||
@@ -44,6 +49,16 @@ class Counter extends Widget<WEnv> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class WidgetA extends Widget<WEnv> {
|
||||||
|
name = "a";
|
||||||
|
template = `<div>Hello<t t-widget="b"/></div>`;
|
||||||
|
widgets = { b: WidgetB };
|
||||||
|
}
|
||||||
|
|
||||||
|
class WidgetB extends Widget<WEnv> {
|
||||||
|
template = `<div>world</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Tests
|
// Tests
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -269,23 +284,26 @@ describe("destroy method", () => {
|
|||||||
widget.destroy();
|
widget.destroy();
|
||||||
expect(count).toBe(1);
|
expect(count).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("destroy remove the parent/children link", async () => {
|
||||||
|
const parent = new WidgetA(env);
|
||||||
|
await parent.mount(fixture);
|
||||||
|
|
||||||
|
const child = children(parent)[0];
|
||||||
|
expect(child.__widget__.parent).toBe(parent);
|
||||||
|
expect(children(parent).length).toBe(1);
|
||||||
|
child.destroy();
|
||||||
|
expect(child.__widget__.parent).toBe(null);
|
||||||
|
expect(children(parent).length).toBe(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("composition", () => {
|
describe("composition", () => {
|
||||||
class WidgetA extends Widget<WEnv> {
|
|
||||||
name = "a";
|
|
||||||
template = `<div>Hello<t t-widget="b"/></div>`;
|
|
||||||
widgets = { b: WidgetB };
|
|
||||||
}
|
|
||||||
class WidgetB extends Widget<WEnv> {
|
|
||||||
template = `<div>world</div>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
test("a widget with a sub widget", async () => {
|
test("a widget with a sub widget", async () => {
|
||||||
const widget = new WidgetA(env);
|
const widget = new WidgetA(env);
|
||||||
await widget.mount(fixture);
|
await widget.mount(fixture);
|
||||||
expect(fixture.innerHTML).toBe("<div>Hello<div>world</div></div>");
|
expect(fixture.innerHTML).toBe("<div>Hello<div>world</div></div>");
|
||||||
expect(widget.__widget__.children[0].__widget__.parent).toBe(widget);
|
expect(children(widget)[0].__widget__.parent).toBe(widget);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("t-refs on widget are widgets", async () => {
|
test("t-refs on widget are widgets", async () => {
|
||||||
@@ -322,11 +340,11 @@ describe("composition", () => {
|
|||||||
await widget.mount(fixture);
|
await widget.mount(fixture);
|
||||||
|
|
||||||
expect((<any>widget.__widget__.vnode!.children![1]).elm).toBe(
|
expect((<any>widget.__widget__.vnode!.children![1]).elm).toBe(
|
||||||
(<any>widget.__widget__.children[0].__widget__.vnode).elm
|
(<any>children(widget)[0].__widget__.vnode).elm
|
||||||
);
|
);
|
||||||
await widget.__widget__.children[0].render();
|
await children(widget)[0].render();
|
||||||
expect((<any>widget.__widget__.vnode!.children![1]).elm).toBe(
|
expect((<any>widget.__widget__.vnode!.children![1]).elm).toBe(
|
||||||
(<any>widget.__widget__.children[0].__widget__.vnode).elm
|
(<any>children(widget)[0].__widget__.vnode).elm
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -334,6 +352,6 @@ describe("composition", () => {
|
|||||||
const widget = new WidgetA(env);
|
const widget = new WidgetA(env);
|
||||||
await widget.mount(fixture);
|
await widget.mount(fixture);
|
||||||
|
|
||||||
expect(widget.__widget__.children[0].env).toBe(env);
|
expect(children(widget)[0].env).toBe(env);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user