[FIX] component: make arrow-function capture backwards compatible

When fixing the absence of capture for arrow functions passed as props,
we unintentionally introduced a breaking change: bare function calls in
the arrow functions used to be called  with the rendering context as
their this value and this was no longer the case.

This commit fixes that by intentionally not capturing the value of
functions that are called withing the arrow function.
This commit is contained in:
Samuel Degueldre
2021-12-07 15:09:21 +01:00
committed by aab-odoo
parent 73f94fba3f
commit 0bc9573a8a
4 changed files with 108 additions and 4 deletions
+43
View File
@@ -1920,6 +1920,49 @@ describe("props evaluation ", () => {
expect(env.qweb.templates.Child.fn.toString()).toMatchSnapshot();
});
test("bare function calls in arrow function has rendering context as 'this'", async () => {
expect.assertions(7);
let child, parent;
class Child extends Component {
setup() {
child = this;
}
}
env.qweb.addTemplate("Child", `<span><t t-esc="props.value"/></span>`);
class Parent extends Component {
static components = { Child };
state = useState({ val: 42 });
setup() {
parent = this;
}
setValue(value) {
// 'this' is the rendering context, NOT the instance
expect(this).not.toBe(parent);
// the state in the rendering context should be the same as the instance's
expect(this.state).toBe(parent.state);
expect((this as any).ctxVal).toBe(2);
this.state.val = value;
}
}
env.qweb.addTemplate(
"Parent",
`<div>
<t t-set="ctxVal" t-value="2"/>
<Child callback="value => setValue(value)" value="state.val"/>
</div>`
);
const widget = new Parent();
await widget.mount(fixture);
expect(fixture.innerHTML).toBe("<div><span>42</span></div>");
child.props.callback(123);
await nextTick();
expect(fixture.innerHTML).toBe("<div><span>123</span></div>");
expect(env.qweb.templates.Parent.fn.toString()).toMatchSnapshot();
expect(env.qweb.templates.Child.fn.toString()).toMatchSnapshot();
});
test("arrow function prop captures context component instance as 'this' inside slot", async () => {
expect.assertions(7);
let child, parent;