[IMP] devtools: add __owl__ access.

To be able to make devtools, we need access some inner state of a
component. We create a __owl_devtools__ variable on components.

Just like in Vue js, we attach it to the HTMLElement of a component.
It's how we give it to the "outside world", through the DOM.

For its update, we use the onMounted and onPatched hook.
This commit is contained in:
Simon Genin (ges)
2020-11-09 16:56:30 +01:00
parent c8a27aa1a3
commit 9e2202c02a
3 changed files with 40 additions and 4 deletions
+2 -2
View File
@@ -13,8 +13,8 @@
"node": ">=10.15.3" "node": ">=10.15.3"
}, },
"scripts": { "scripts": {
"build:bundle": "rollup -c", "dev": "rollup -c",
"build": "npm run build:bundle", "build": "NODE_ENV=production rollup -c",
"test": "jest", "test": "jest",
"test:watch": "jest --watch", "test:watch": "jest --watch",
"tools:serve": "python3 tools/server.py || python tools/server.py", "tools:serve": "python3 tools/server.py || python tools/server.py",
+38 -1
View File
@@ -8,6 +8,7 @@ import "./props_validation";
import { Scheduler, scheduler } from "./scheduler"; import { Scheduler, scheduler } from "./scheduler";
import { activateSheet } from "./styles"; import { activateSheet } from "./styles";
import { Browser, browser } from "../browser"; import { Browser, browser } from "../browser";
import { onMounted, onPatched } from "../hooks";
/** /**
* Owl Component System * Owl Component System
@@ -91,8 +92,24 @@ interface Internal<T extends Env> {
refs: { [key: string]: Component<any, T> | HTMLElement | undefined } | null; refs: { [key: string]: Component<any, T> | HTMLElement | undefined } | null;
} }
interface DevToolsAccess {
props?: any;
defaultProps?: any;
template?: string | null;
state: Observer;
tag: String;
depth: number,
}
export const portalSymbol = Symbol("portal"); // FIXME export const portalSymbol = Symbol("portal"); // FIXME
/**
* It is required for the dev tools to have access to the __owl__ element.
*/
interface HTMLElementWithDevToolsAccess extends HTMLElement {
__owl_devtools__: DevToolsAccess
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Component // Component
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -110,11 +127,13 @@ export class Component<Props extends {} = any, T extends Env = Env> {
// expose scheduler s.t. it can be mocked for testing purposes // expose scheduler s.t. it can be mocked for testing purposes
static scheduler: Scheduler = scheduler; static scheduler: Scheduler = scheduler;
__devtools__: DevToolsAccess;
/** /**
* The `el` is the root element of the component. Note that it could be null: * The `el` is the root element of the component. Note that it could be null:
* this is the case if the component is not mounted yet, or is destroyed. * this is the case if the component is not mounted yet, or is destroyed.
*/ */
get el(): HTMLElement | null { get el(): HTMLElementWithDevToolsAccess | null {
return this.__owl__.vnode ? (<any>this).__owl__.vnode.elm : null; return this.__owl__.vnode ? (<any>this).__owl__.vnode.elm : null;
} }
@@ -208,6 +227,24 @@ export class Component<Props extends {} = any, T extends Env = Env> {
if (constr.style) { if (constr.style) {
this.__applyStyles(constr); this.__applyStyles(constr);
} }
// DevTools hooks
onMounted(() => {
this.__devtools__ = {
depth: this.__owl__.depth,
state: this.__owl__.observer,
tag: this.constructor.name
};
this.__devtools__.defaultProps = defaultProps;
this.__devtools__.props = this.props;
this.__devtools__.template = template;
this.el.__owl_devtools__ = this.__devtools__;
})
onPatched(() => {
this.__devtools__.depth = this.__owl__.depth,
this.el.__owl_devtools__ = this.__devtools__;
})
} }
/** /**
-1
View File
@@ -21,7 +21,6 @@ export class Observer {
rev: number = 1; rev: number = 1;
allowMutations: boolean = true; allowMutations: boolean = true;
weakMap: WeakMap<any, any> = new WeakMap(); weakMap: WeakMap<any, any> = new WeakMap();
notifyCB() {} notifyCB() {}
observe<T>(value: T, parent?: any): T { observe<T>(value: T, parent?: any): T {