[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"
},
"scripts": {
"build:bundle": "rollup -c",
"build": "npm run build:bundle",
"dev": "rollup -c",
"build": "NODE_ENV=production rollup -c",
"test": "jest",
"test:watch": "jest --watch",
"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 { activateSheet } from "./styles";
import { Browser, browser } from "../browser";
import { onMounted, onPatched } from "../hooks";
/**
* Owl Component System
@@ -91,8 +92,24 @@ interface Internal<T extends Env> {
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
/**
* It is required for the dev tools to have access to the __owl__ element.
*/
interface HTMLElementWithDevToolsAccess extends HTMLElement {
__owl_devtools__: DevToolsAccess
}
//------------------------------------------------------------------------------
// 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
static scheduler: Scheduler = scheduler;
__devtools__: DevToolsAccess;
/**
* 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.
*/
get el(): HTMLElement | null {
get el(): HTMLElementWithDevToolsAccess | 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) {
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;
allowMutations: boolean = true;
weakMap: WeakMap<any, any> = new WeakMap();
notifyCB() {}
observe<T>(value: T, parent?: any): T {