import { OwlError } from "../common/owl_error"; import { version } from "../version"; import { Component, ComponentConstructor, Props } from "./component"; import { ComponentNode, saveCurrent } from "./component_node"; import { handleError, nodeErrorHandlers } from "./error_handling"; import { Fiber, MountOptions, RootFiber } from "./fibers"; import { reactive, toRaw } from "./reactivity"; import { Scheduler } from "./scheduler"; import { validateProps } from "./template_helpers"; import { TemplateSet, TemplateSetConfig } from "./template_set"; import { validateTarget } from "./utils"; // reimplement dev mode stuff see last change in 0f7a8289a6fb8387c3c1af41c6664b2a8448758f export interface Env { [key: string]: any; } export interface RootConfig
{ props?: P; env?: E; } export interface AppConfig
extends TemplateSetConfig, RootConfig
{
name?: string;
test?: boolean;
warnIfNoStaticProps?: boolean;
}
let hasBeenLogged = false;
export const DEV_MSG = () => {
const hash = (window as any).owl ? (window as any).owl.__info__.hash : "master";
return `Owl is running in 'dev' mode.
This is not suitable for production use.
See https://github.com/odoo/owl/blob/${hash}/doc/reference/app.md#configuration for more information.`;
};
const apps = new Set {
node: ComponentNode | null;
mount(target: HTMLElement | ShadowRoot, options?: MountOptions): Promise ;
props: P;
env: E;
scheduler = new Scheduler();
subRoots: Set | null = null;
warnIfNoStaticProps: boolean;
_lastRootEl: HTMLElement | ShadowRoot | null = null; // temporary ref to propagate to roots
constructor(Root: ComponentConstructor , config: AppConfig = {}) {
super(config);
this.name = config.name || "";
this.Root = Root;
apps.add(this);
if (config.test) {
this.dev = true;
}
this.warnIfNoStaticProps = config.warnIfNoStaticProps || false;
if (this.dev && !config.test && !hasBeenLogged) {
console.info(DEV_MSG());
hasBeenLogged = true;
}
const env = config.env || {};
const descrs = Object.getOwnPropertyDescriptors(env);
this.env = Object.freeze(Object.create(Object.getPrototypeOf(env), descrs));
this.props = config.props || ({} as P);
}
mount(
target: HTMLElement | ShadowRoot,
options?: MountOptions
): Promise (
name: string | null,
isStatic: boolean,
hasSlotsProp: boolean,
hasDynamicPropList: boolean,
propList: string[]
) {
const isDynamic = !isStatic;
let arePropsDifferent: (p1: Object, p2: Object) => boolean;
const hasNoProp = propList.length === 0;
if (hasSlotsProp) {
arePropsDifferent = (_1, _2) => true;
} else if (hasDynamicPropList) {
arePropsDifferent = function (props1: Props, props2: Props) {
for (let k in props1) {
if (props1[k] !== props2[k]) {
return true;
}
}
return Object.keys(props1).length !== Object.keys(props2).length;
};
} else if (hasNoProp) {
arePropsDifferent = (_1: any, _2: any) => false;
} else {
arePropsDifferent = function (props1: Props, props2: Props) {
for (let p of propList) {
if (props1[p] !== props2[p]) {
return true;
}
}
return false;
};
}
const updateAndRender = ComponentNode.prototype.updateAndRender;
const initiateRender = ComponentNode.prototype.initiateRender;
return (props: P, key: string, ctx: ComponentNode, parent: any, C: any) => {
let children = ctx.children;
let node: any = children[key];
if (isDynamic && node && node.component.constructor !== C) {
node = undefined;
}
const parentFiber = ctx.fiber!;
if (node) {
if (arePropsDifferent(node.props, props) || parentFiber.deep || node.forceNextRender) {
node.forceNextRender = false;
updateAndRender.call(node, props, parentFiber);
}
} else {
// new component
if (isStatic) {
const components = parent.constructor.components;
if (!components) {
throw new OwlError(
`Cannot find the definition of component "${name}", missing static components key in parent`
);
}
C = components[name as any];
if (!C) {
throw new OwlError(`Cannot find the definition of component "${name}"`);
} else if (!(C.prototype instanceof Component)) {
throw new OwlError(
`"${name}" is not a Component. It must inherit from the Component class`
);
}
}
node = new ComponentNode(C, props, this, ctx, key);
children[key] = node;
initiateRender.call(node, new Fiber(node, parentFiber));
}
parentFiber.childrenMap[key] = node;
return node;
};
}
handleError(...args: Parameters ,
target: HTMLElement,
config: AppConfig & MountOptions = {}
): Promise