[IMP] component: disable mutations in render phase

closes #48
This commit is contained in:
Géry Debongnie
2019-04-17 16:52:39 +02:00
parent 4b30d0b412
commit 29111a5c10
2 changed files with 26 additions and 1 deletions
+3 -1
View File
@@ -227,7 +227,6 @@ export class Component<
}
this._patch(vnode);
target.appendChild(this.el!);
this._observeState();
if (document.body.contains(target)) {
this._visitSubTree(w => {
@@ -357,6 +356,7 @@ export class Component<
true
);
}
this._observeState();
return this._render();
});
return this.__owl__.renderPromise;
@@ -366,11 +366,13 @@ export class Component<
this.__owl__.renderId++;
const promises: Promise<void>[] = [];
const template = this.inlineTemplate || this.template;
this.__owl__.observer.allowMutations = false;
let vnode = this.env.qweb.render(template, this, {
promises,
handlers: this.__owl__.boundHandlers,
forceUpdate: force
});
this.__owl__.observer.allowMutations = true;
// this part is critical for the patching process to be done correctly. The
// tricky part is that a child widget can be rerendered on its own, which
+23
View File
@@ -1426,4 +1426,27 @@ describe("widget and observable state", () => {
await nextMicroTick();
expect(fixture.innerHTML).toBe("<div>beer</div>");
});
test("subwidgets cannot change observable state received from parent", async () => {
expect.assertions(1);
class Parent extends Widget {
state = { obj: { coffee: 1 } };
widgets = { Child };
inlineTemplate = `<div><t t-widget="Child" t-props="state.obj"/></div>`;
}
class Child extends Widget {
constructor(parent, props) {
super(parent, props);
props.coffee = 2;
}
}
const parent = new Parent(env);
try {
await parent.mount(fixture);
} catch (e) {
expect(e.message).toBe(
'Observed state cannot be changed here! (key: "coffee", val: "2")'
);
}
});
});