mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] debug tools: do not crash on non json-stringifiable props
closes #595
This commit is contained in:
+1
-1
@@ -102,7 +102,7 @@ logging useful information is extremely valuable. There is a [javascript file](.
|
||||
Once it is executed, it will log a lot of information on each component main hooks. The following code is a minified version to make it easier to copy/paste:
|
||||
|
||||
```
|
||||
function debugOwl(t,n){let e,o="[OWL_DEBUG]";function s(t){let n=JSON.stringify(t||{});return n.length>200&&(n=n.slice(0,200)+"..."),n}if(Object.defineProperty(t.Component,"current",{get:()=>e,set(i){e=i;const r=i.constructor.name;if(n.componentBlackList&&n.componentBlackList.test(r))return;if(n.componentWhiteList&&!n.componentWhiteList.test(r))return;let l;Object.defineProperty(e,"__owl__",{get:()=>l,set(e){!function(e,i,r){let l=`${i}<id=${r}>`,c=t=>console.log(`${o} ${l} ${t}`),u=t=>(!n.methodBlackList||!n.methodBlackList.includes(t))&&!(n.methodWhiteList&&!n.methodWhiteList.includes(t));u("constructor")&&c(`constructor, props=${s(e.props)}`);u("willStart")&&t.hooks.onWillStart(()=>{c("willStart")});u("mounted")&&t.hooks.onMounted(()=>{c("mounted")});u("willUpdateProps")&&t.hooks.onWillUpdateProps(t=>{c(`willUpdateProps, nextprops=${s(t)}`)});u("willPatch")&&t.hooks.onWillPatch(()=>{c("willPatch")});u("patched")&&t.hooks.onPatched(()=>{c("patched")});u("willUnmount")&&t.hooks.onWillUnmount(()=>{c("willUnmount")});const d=e.__render.bind(e);e.__render=function(...t){c("rendering template"),d(...t)};const h=e.render.bind(e);e.render=function(...t){const n=e.__owl__;let o="render";return n.isMounted||n.currentFiber||(o+=" (warning: component is not mounted, this render has no effect)"),c(o),h(...t)};const p=e.mount.bind(e);e.mount=function(...t){return c("mount"),p(...t)}}(i,r,(l=e).id)}})}}),n.logScheduler){let n=t.Component.scheduler.start,e=t.Component.scheduler.stop;t.Component.scheduler.start=function(){this.isRunning||console.log(`${o} scheduler: start running tasks queue`),n.call(this)},t.Component.scheduler.stop=function(){this.isRunning&&console.log(`${o} scheduler: stop running tasks queue`),e.call(this)}}if(n.logStore){let n=t.Store.prototype.dispatch;t.Store.prototype.dispatch=function(t,...e){return console.log(`${o} store: action '${t}' dispatched. Payload: '${s(e)}'`),n.call(this,t,...e)}}}
|
||||
function debugOwl(t,e){let n,o="[OWL_DEBUG]";function r(t){let e;try{e=JSON.stringify(t||{})}catch(t){e="<JSON error>"}return e.length>200&&(e=e.slice(0,200)+"..."),e}if(Object.defineProperty(t.Component,"current",{get:()=>n,set(s){n=s;const i=s.constructor.name;if(e.componentBlackList&&e.componentBlackList.test(i))return;if(e.componentWhiteList&&!e.componentWhiteList.test(i))return;let l;Object.defineProperty(n,"__owl__",{get:()=>l,set(n){!function(n,s,i){let l=`${s}<id=${i}>`,c=t=>console.log(`${o} ${l} ${t}`),u=t=>(!e.methodBlackList||!e.methodBlackList.includes(t))&&!(e.methodWhiteList&&!e.methodWhiteList.includes(t));u("constructor")&&c(`constructor, props=${r(n.props)}`);u("willStart")&&t.hooks.onWillStart(()=>{c("willStart")});u("mounted")&&t.hooks.onMounted(()=>{c("mounted")});u("willUpdateProps")&&t.hooks.onWillUpdateProps(t=>{c(`willUpdateProps, nextprops=${r(t)}`)});u("willPatch")&&t.hooks.onWillPatch(()=>{c("willPatch")});u("patched")&&t.hooks.onPatched(()=>{c("patched")});u("willUnmount")&&t.hooks.onWillUnmount(()=>{c("willUnmount")});const d=n.__render.bind(n);n.__render=function(...t){c("rendering template"),d(...t)};const h=n.render.bind(n);n.render=function(...t){const e=n.__owl__;let o="render";return e.isMounted||e.currentFiber||(o+=" (warning: component is not mounted, this render has no effect)"),c(o),h(...t)};const p=n.mount.bind(n);n.mount=function(...t){return c("mount"),p(...t)}}(s,i,(l=n).id)}})}}),e.logScheduler){let e=t.Component.scheduler.start,n=t.Component.scheduler.stop;t.Component.scheduler.start=function(){this.isRunning||console.log(`${o} scheduler: start running tasks queue`),e.call(this)},t.Component.scheduler.stop=function(){this.isRunning&&console.log(`${o} scheduler: stop running tasks queue`),n.call(this)}}if(e.logStore){let e=t.Store.prototype.dispatch;t.Store.prototype.dispatch=function(t,...n){return console.log(`${o} store: action '${t}' dispatched. Payload: '${r(n)}'`),e.call(this,t,...n)}}}
|
||||
debugOwl(owl, {
|
||||
// componentBlackList: /App/, // regexp
|
||||
// componentWhiteList: /SomeComponent/, // regexp
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* We can only make one test per file, since the debug tool modify in place
|
||||
* the owl object in a way that is difficult to undo.
|
||||
*/
|
||||
|
||||
import { debugOwl } from "../../tools/debug";
|
||||
import * as owl from "../../src/index";
|
||||
|
||||
import { Component, Env } from "../../src/component/component";
|
||||
import { xml } from "../../src/tags";
|
||||
import { makeTestFixture, makeTestEnv } from "../helpers";
|
||||
|
||||
let fixture: HTMLElement = makeTestFixture();
|
||||
let env: Env = makeTestEnv();
|
||||
Component.env = env;
|
||||
|
||||
debugOwl(owl, { logScheduler: true });
|
||||
|
||||
test("log a sub component with non stringifiable props", async () => {
|
||||
const steps: string[] = [];
|
||||
const log = console.log;
|
||||
console.log = arg => steps.push(arg);
|
||||
|
||||
class Child extends Component<any,any> {
|
||||
static template = xml`<span><t t-esc="props.obj.val"/></span>`;
|
||||
}
|
||||
|
||||
const circularObject: any = {val: 1};
|
||||
circularObject.circularObject = circularObject;
|
||||
|
||||
class Parent extends Component<any, any> {
|
||||
static template = xml`<div><Child obj="obj"/></div>`;
|
||||
static components = { Child };
|
||||
obj = circularObject;
|
||||
|
||||
}
|
||||
|
||||
const parent = new Parent(null, {});
|
||||
await parent.mount(fixture);
|
||||
parent.unmount();
|
||||
|
||||
expect(steps).toEqual([
|
||||
"[OWL_DEBUG] Parent<id=1> constructor, props={}",
|
||||
"[OWL_DEBUG] Parent<id=1> mount",
|
||||
"[OWL_DEBUG] Parent<id=1> willStart",
|
||||
"[OWL_DEBUG] scheduler: start running tasks queue",
|
||||
"[OWL_DEBUG] Parent<id=1> rendering template",
|
||||
"[OWL_DEBUG] Child<id=2> constructor, props=<JSON error>",
|
||||
"[OWL_DEBUG] Child<id=2> willStart",
|
||||
"[OWL_DEBUG] Child<id=2> rendering template",
|
||||
"[OWL_DEBUG] Child<id=2> mounted",
|
||||
"[OWL_DEBUG] Parent<id=1> mounted",
|
||||
"[OWL_DEBUG] scheduler: stop running tasks queue",
|
||||
"[OWL_DEBUG] Parent<id=1> willUnmount",
|
||||
"[OWL_DEBUG] Child<id=2> willUnmount"
|
||||
]);
|
||||
console.log = log;
|
||||
});
|
||||
+6
-1
@@ -35,7 +35,12 @@
|
||||
});
|
||||
|
||||
function toStr(obj) {
|
||||
let str = JSON.stringify(obj || {});
|
||||
let str;
|
||||
try {
|
||||
str = JSON.stringify(obj || {});
|
||||
} catch (e) {
|
||||
str = "<JSON error>";
|
||||
}
|
||||
if (str.length > 200) {
|
||||
str = str.slice(0, 200) + "...";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user