[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); this._patch(vnode);
target.appendChild(this.el!); target.appendChild(this.el!);
this._observeState();
if (document.body.contains(target)) { if (document.body.contains(target)) {
this._visitSubTree(w => { this._visitSubTree(w => {
@@ -357,6 +356,7 @@ export class Component<
true true
); );
} }
this._observeState();
return this._render(); return this._render();
}); });
return this.__owl__.renderPromise; return this.__owl__.renderPromise;
@@ -366,11 +366,13 @@ export class Component<
this.__owl__.renderId++; this.__owl__.renderId++;
const promises: Promise<void>[] = []; const promises: Promise<void>[] = [];
const template = this.inlineTemplate || this.template; const template = this.inlineTemplate || this.template;
this.__owl__.observer.allowMutations = false;
let vnode = this.env.qweb.render(template, this, { let vnode = this.env.qweb.render(template, this, {
promises, promises,
handlers: this.__owl__.boundHandlers, handlers: this.__owl__.boundHandlers,
forceUpdate: force forceUpdate: force
}); });
this.__owl__.observer.allowMutations = true;
// this part is critical for the patching process to be done correctly. The // 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 // 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(); await nextMicroTick();
expect(fixture.innerHTML).toBe("<div>beer</div>"); 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")'
);
}
});
}); });