mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] components: wrap onWillRender/onRendered hooks instead of renderFn
Previously, we were wrapping the entire renderFn in a try/catch, causing errors during template execution to be caught and wrapped by onWillRender/onRendered which is undesirable. Now we only wrap the hook that's being registered.
This commit is contained in:
committed by
Géry Debongnie
parent
14d2328c88
commit
67f86a4ab8
@@ -77,21 +77,23 @@ export function onWillRender(fn: () => void | any) {
|
|||||||
const node = getCurrent();
|
const node = getCurrent();
|
||||||
const renderFn = node.renderFn;
|
const renderFn = node.renderFn;
|
||||||
const decorate = node.app.dev ? wrapError : (fn: any) => fn;
|
const decorate = node.app.dev ? wrapError : (fn: any) => fn;
|
||||||
node.renderFn = decorate(() => {
|
fn = decorate(fn.bind(node.component), "onWillRender");
|
||||||
fn.call(node.component);
|
node.renderFn = () => {
|
||||||
|
fn();
|
||||||
return renderFn();
|
return renderFn();
|
||||||
}, "onWillRender");
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function onRendered(fn: () => void | any) {
|
export function onRendered(fn: () => void | any) {
|
||||||
const node = getCurrent();
|
const node = getCurrent();
|
||||||
const renderFn = node.renderFn;
|
const renderFn = node.renderFn;
|
||||||
const decorate = node.app.dev ? wrapError : (fn: any) => fn;
|
const decorate = node.app.dev ? wrapError : (fn: any) => fn;
|
||||||
node.renderFn = decorate(() => {
|
fn = decorate(fn.bind(node.component), "onRendered");
|
||||||
|
node.renderFn = () => {
|
||||||
const result = renderFn();
|
const result = renderFn();
|
||||||
fn.call(node.component);
|
fn();
|
||||||
return result;
|
return result;
|
||||||
}, "onRendered");
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
type OnErrorCallback = (error: any) => void | any;
|
type OnErrorCallback = (error: any) => void | any;
|
||||||
|
|||||||
@@ -1156,6 +1156,19 @@ exports[`errors and promises errors in mounted and in willUnmount 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`errors and promises errors in onWillRender/onRender aren't wrapped more than once 1`] = `
|
||||||
|
"function anonymous(bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div>abc</div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return block1();
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`errors and promises errors in rerender 1`] = `
|
exports[`errors and promises errors in rerender 1`] = `
|
||||||
"function anonymous(bdom, helpers
|
"function anonymous(bdom, helpers
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import {
|
|||||||
onPatched,
|
onPatched,
|
||||||
onWillPatch,
|
onWillPatch,
|
||||||
onWillStart,
|
onWillStart,
|
||||||
|
onWillRender,
|
||||||
|
onRendered,
|
||||||
onWillUnmount,
|
onWillUnmount,
|
||||||
useState,
|
useState,
|
||||||
xml,
|
xml,
|
||||||
@@ -199,6 +201,50 @@ describe("errors and promises", () => {
|
|||||||
expect(mockConsoleWarn).toBeCalledTimes(1);
|
expect(mockConsoleWarn).toBeCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("errors in onWillRender/onRender aren't wrapped more than once", async () => {
|
||||||
|
class App extends Component {
|
||||||
|
static template = xml`<div>abc</div>`;
|
||||||
|
setup() {
|
||||||
|
onWillRender(() => {
|
||||||
|
throw new Error("boom in onWillRender");
|
||||||
|
});
|
||||||
|
onRendered(() => {
|
||||||
|
throw new Error("boom in onRendered");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let error: Error;
|
||||||
|
try {
|
||||||
|
await mount(App, fixture, { test: true });
|
||||||
|
} catch (e) {
|
||||||
|
error = e as Error;
|
||||||
|
}
|
||||||
|
expect(error!).toBeDefined();
|
||||||
|
expect(error!.message).toBe(
|
||||||
|
`The following error occurred in onWillRender: "boom in onWillRender"`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("error while rendering component isn't wrapped by onWillRender/onRendered", async () => {
|
||||||
|
class App extends Component {
|
||||||
|
static template = xml`<div t-att-class="{ 'invalid: 5 }">abc</div>`;
|
||||||
|
setup() {
|
||||||
|
onWillRender(() => {});
|
||||||
|
onRendered(() => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let error: Error;
|
||||||
|
try {
|
||||||
|
await mount(App, fixture, { test: true });
|
||||||
|
} catch (e) {
|
||||||
|
error = e as Error;
|
||||||
|
}
|
||||||
|
expect(error!).toBeDefined();
|
||||||
|
expect(error!.message).toBe("Tokenizer error: could not tokenize `{ 'invalid: 5 }`");
|
||||||
|
});
|
||||||
|
|
||||||
test("an error in willPatch call will reject the render promise", async () => {
|
test("an error in willPatch call will reject the render promise", async () => {
|
||||||
class Root extends Component {
|
class Root extends Component {
|
||||||
static template = xml`<div><t t-esc="val"/></div>`;
|
static template = xml`<div><t t-esc="val"/></div>`;
|
||||||
|
|||||||
Reference in New Issue
Block a user