[IMP] Owl: update to 1.0.0-beta5

Update of the Owl library.
Also added "_lt" to the default test environment properties.
This commit is contained in:
Julien Mougenot
2020-01-06 14:37:16 +00:00
parent 35163f7785
commit 3cf49e1913
2 changed files with 270 additions and 156 deletions
+269 -156
View File
@@ -1,6 +1,6 @@
(function (exports) {
'use strict';
(function (exports) {
'use strict';
/**
* We define here a simple event bus: it can
* - emit events
@@ -64,8 +64,8 @@
clear() {
this.subscriptions = {};
}
}
}
/**
* Owl Observer
*
@@ -150,8 +150,8 @@
metadata.rev++;
} while ((parent = metadata.parent) && parent !== target);
}
}
}
//------------------------------------------------------------------------------
// module/props.ts
//------------------------------------------------------------------------------
@@ -355,8 +355,8 @@
}
}
}
const classModule = { create: updateClass, update: updateClass };
const classModule = { create: updateClass, update: updateClass };
/**
* Owl VDOM
*
@@ -787,10 +787,10 @@
}
}
return vnode(sel, data, children, text, undefined);
}
const patch = init([eventListenersModule, attrsModule, propsModule, classModule]);
}
const patch = init([eventListenersModule, attrsModule, propsModule, classModule]);
/**
* Owl QWeb Expression Parser
*
@@ -837,7 +837,7 @@
};
// note that the space after typeof is relevant. It makes sure that the formatted
// expression has a space after typeof
const OPERATORS = ".,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%,typeof ,=>,=,;".split(",");
const OPERATORS = "...,.,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%,typeof ,=>,=,;".split(",");
let tokenizeString = function (expr) {
let s = expr[0];
let start = s;
@@ -1027,8 +1027,8 @@
}
}
return tokens.map(t => t.value).join("");
}
}
const INTERP_REGEXP = /\{\{.*?\}\}/g;
//------------------------------------------------------------------------------
// Compilation Context
@@ -1052,10 +1052,11 @@
this.inPreTag = false;
this.allowMultipleRoots = false;
this.hasParentWidget = false;
this.currentKey = "";
this.hasKey0 = false;
this.keyStack = [];
this.rootContext = this;
this.templateName = name || "noname";
this.addLine("var h = this.h;");
this.addLine("let h = this.h;");
}
generateID() {
return CompilationContext.nextID++;
@@ -1070,21 +1071,15 @@
*/
generateTemplateKey(prefix = "") {
const id = this.generateID();
if (this.loopNumber === 0 && !this.currentKey) {
if (this.loopNumber === 0 && !this.hasKey0) {
return `'${prefix}__${id}__'`;
}
let locationExpr = `\`${prefix}__${id}__`;
for (let i = 0; i < this.loopNumber - 1; i++) {
locationExpr += `\${i${i + 1}}__`;
}
if (this.currentKey) {
const k = this.currentKey;
this.addLine(`let k${id} = ${locationExpr}\` + ${k};`);
}
else {
locationExpr += this.loopNumber ? `\${i${this.loopNumber}}__\`` : "`";
this.addLine(`let k${id} = ${locationExpr};`);
let key = `\`${prefix}__${id}__`;
let start = this.hasKey0 ? 0 : 1;
for (let i = start; i < this.loopNumber + 1; i++) {
key += `\${key${i}}__`;
}
this.addLine(`let k${id} = ${key}\`;`);
return `k${id}`;
}
generateCode() {
@@ -1133,10 +1128,10 @@
return newContext;
}
indent() {
this.indentLevel++;
this.rootContext.indentLevel++;
}
dedent() {
this.indentLevel--;
this.rootContext.indentLevel--;
}
addLine(line) {
const prefix = new Array(this.indentLevel + 2).join(" ");
@@ -1188,7 +1183,7 @@
startProtectScope() {
const protectID = this.generateID();
this.rootContext.shouldDefineScope = true;
this.addLine(`const _origScope${protectID} = scope;`);
this.addLine(`let _origScope${protectID} = scope;`);
this.addLine(`scope = Object.assign(Object.create(context), scope);`);
return protectID;
}
@@ -1196,8 +1191,8 @@
this.addLine(`scope = _origScope${protectID};`);
}
}
CompilationContext.nextID = 1;
CompilationContext.nextID = 1;
/**
* Owl Utils
*
@@ -1292,18 +1287,18 @@
}
}
return true;
}
var _utils = /*#__PURE__*/Object.freeze({
__proto__: null,
whenReady: whenReady,
loadJS: loadJS,
loadFile: loadFile,
escape: escape,
debounce: debounce,
shallowEqual: shallowEqual
});
}
var _utils = /*#__PURE__*/Object.freeze({
__proto__: null,
whenReady: whenReady,
loadJS: loadJS,
loadFile: loadFile,
escape: escape,
debounce: debounce,
shallowEqual: shallowEqual
});
//------------------------------------------------------------------------------
// Const/global stuff/helpers
//------------------------------------------------------------------------------
@@ -1352,7 +1347,7 @@
return vnode.text;
}
})
.join();
.join("");
},
getComponent(obj) {
while (obj && !obj.hasOwnProperty("__owl__")) {
@@ -1570,7 +1565,7 @@
}
});
}
_compile(name, elem, parentContext) {
_compile(name, elem, parentContext, defineKey) {
const isDebug = elem.attributes.hasOwnProperty("t-debug");
const ctx = new CompilationContext(name);
if (elem.tagName !== "t") {
@@ -1583,6 +1578,10 @@
ctx.hasParentWidget = true;
ctx.shouldDefineResult = false;
ctx.addLine(`let c${ctx.parentNode} = extra.parentNode;`);
if (defineKey) {
ctx.addLine(`let key0 = extra.key || "";`);
ctx.hasKey0 = true;
}
}
this._compileNode(elem, ctx);
if (!parentContext) {
@@ -1652,16 +1651,13 @@
// this is an unusual situation: this text node is the result of the
// template rendering.
let nodeID = ctx.generateID();
ctx.addLine(`var vn${nodeID} = {text: \`${text}\`};`);
ctx.addLine(`let vn${nodeID} = {text: \`${text}\`};`);
ctx.addLine(`result = vn${nodeID};`);
ctx.rootContext.rootNode = nodeID;
ctx.rootContext.parentTextNode = nodeID;
}
return;
}
if (ctx !== ctx.rootContext) {
ctx = ctx.subContext("currentKey", ctx.currentKey);
}
const firstLetter = node.tagName[0];
if (firstLetter === firstLetter.toUpperCase()) {
// this is a component, we modify in place the xml document to change
@@ -1837,7 +1833,7 @@
}
}
else {
ctx.addLine(`var _${attID} = '${value}';`);
ctx.addLine(`let _${attID} = '${value}';`);
if (!name.match(/^[a-zA-Z]+$/)) {
// attribute contains 'non letters' => we want to quote it
name = '"' + name + '"';
@@ -1873,12 +1869,12 @@
const attValue = node.getAttribute(attName);
if (attValue) {
const attValueID = ctx.generateID();
ctx.addLine(`var _${attValueID} = ${formattedValue};`);
ctx.addLine(`let _${attValueID} = ${formattedValue};`);
formattedValue = `'${attValue}' + (_${attValueID} ? ' ' + _${attValueID} : '')`;
const attrIndex = attrs.findIndex(att => att.startsWith(attName + ":"));
attrs.splice(attrIndex, 1);
}
ctx.addLine(`var _${attID} = ${formattedValue};`);
ctx.addLine(`let _${attID} = ${formattedValue};`);
attrs.push(`${attName}: _${attID}`);
handleBooleanProps(attName, attID);
}
@@ -1893,23 +1889,23 @@
const attID = ctx.generateID();
let staticVal = node.getAttribute(attName);
if (staticVal) {
ctx.addLine(`var _${attID} = '${staticVal} ' + ${formattedExpr};`);
ctx.addLine(`let _${attID} = '${staticVal} ' + ${formattedExpr};`);
}
else {
ctx.addLine(`var _${attID} = ${formattedExpr};`);
ctx.addLine(`let _${attID} = ${formattedExpr};`);
}
attrs.push(`${attName}: _${attID}`);
}
// t-att= attributes
if (name === "t-att") {
let id = ctx.generateID();
ctx.addLine(`var _${id} = ${ctx.formatExpression(value)};`);
ctx.addLine(`let _${id} = ${ctx.formatExpression(value)};`);
tattrs.push(id);
}
}
let nodeID = ctx.generateID();
let nodeKey = ctx.currentKey || nodeID;
const parts = [`key:${nodeKey}`];
let key = ctx.loopNumber || ctx.hasKey0 ? `\`\${key${ctx.loopNumber}}_${nodeID}\`` : nodeID;
const parts = [`key:${key}`];
if (attrs.length + tattrs.length > 0) {
parts.push(`attrs:{${attrs.join(",")}}`);
}
@@ -1934,10 +1930,14 @@
ctx.addLine(`}`);
ctx.closeIf();
}
ctx.addLine(`var vn${nodeID} = h('${node.nodeName}', p${nodeID}, c${nodeID});`);
ctx.addLine(`let vn${nodeID} = h('${node.nodeName}', p${nodeID}, c${nodeID});`);
if (ctx.parentNode) {
ctx.addLine(`c${ctx.parentNode}.push(vn${nodeID});`);
}
else if (ctx.loopNumber || ctx.hasKey0) {
ctx.rootContext.shouldDefineResult = true;
ctx.addLine(`result = vn${nodeID};`);
}
return nodeID;
}
_compileChildren(node, ctx) {
@@ -1964,8 +1964,8 @@
// slots contains sub templates defined with t-set inside t-component nodes, and
// are meant to be used by the t-slot directive.
QWeb.slots = {};
QWeb.nextSlotId = 1;
QWeb.nextSlotId = 1;
const parser = new DOMParser();
function htmlToVDOM(html) {
const doc = parser.parseFromString(html, "text/html");
@@ -1988,8 +1988,8 @@
children.push(htmlToVNode(c));
}
return h(node.tagName, { attrs }, children);
}
}
/**
* Owl QWeb Directives
*
@@ -2024,12 +2024,12 @@
let exprID;
if (typeof value === "string") {
exprID = `_${ctx.generateID()}`;
ctx.addLine(`var ${exprID} = ${ctx.formatExpression(value)};`);
ctx.addLine(`let ${exprID} = ${ctx.formatExpression(value)};`);
}
else {
exprID = `scope.${value.id}`;
}
ctx.addIf(`${exprID} || ${exprID} === 0`);
ctx.addIf(`${exprID} != null`);
if (ctx.escaping) {
let protectID;
if (value.hasBody) {
@@ -2046,7 +2046,7 @@
let nodeID = ctx.generateID();
ctx.rootContext.rootNode = nodeID;
ctx.rootContext.parentTextNode = nodeID;
ctx.addLine(`var vn${nodeID} = {text: ${exprID}};`);
ctx.addLine(`let vn${nodeID} = {text: ${exprID}};`);
if (ctx.rootContext.shouldDefineResult) {
ctx.addLine(`result = vn${nodeID}`);
}
@@ -2118,7 +2118,7 @@
const tempParentNodeID = ctx.generateID();
const _parentNode = ctx.parentNode;
ctx.parentNode = tempParentNodeID;
ctx.addLine(`const c${tempParentNodeID} = new utils.VDomArray();`);
ctx.addLine(`let c${tempParentNodeID} = new utils.VDomArray();`);
const nodeCopy = node.cloneNode(true);
for (let attr of ["t-set", "t-value", "t-if", "t-else", "t-elif"]) {
nodeCopy.removeAttribute(attr);
@@ -2185,6 +2185,7 @@
// Step 1: sanity checks
// ------------------------------------------------
ctx.rootContext.shouldDefineScope = true;
ctx.rootContext.shouldDefineUtils = true;
if (node.nodeName !== "t") {
throw new Error("Invalid tag for t-call directive (should be 't')");
}
@@ -2197,7 +2198,7 @@
// ------------------------------------------------
if (!qweb.subTemplates[subTemplate]) {
qweb.subTemplates[subTemplate] = true;
const subTemplateFn = qweb._compile(subTemplate, nodeTemplate.elem, ctx);
const subTemplateFn = qweb._compile(subTemplate, nodeTemplate.elem, ctx, true);
qweb.subTemplates[subTemplate] = subTemplateFn;
}
// Step 3: compile t-call body if necessary
@@ -2229,14 +2230,18 @@
// Step 4: add the appropriate function call to current component
// ------------------------------------------------
const callingScope = hasBody ? "scope" : "Object.assign(Object.create(context), scope)";
const parentComponent = `utils.getComponent(context)`;
const keyCode = ctx.loopNumber || ctx.hasKey0 ? `, key: ${ctx.generateTemplateKey()}` : "";
const parentNode = ctx.parentNode ? `c${ctx.parentNode}` : "result";
const extra = `Object.assign({}, extra, {parentNode: ${parentNode}, parent: ${parentComponent}${keyCode}})`;
if (ctx.parentNode) {
ctx.addLine(`this.subTemplates['${subTemplate}'].call(this, ${callingScope}, Object.assign({}, extra, {parentNode: c${ctx.parentNode}}));`);
ctx.addLine(`this.subTemplates['${subTemplate}'].call(this, ${callingScope}, ${extra});`);
}
else {
// this is a t-call with no parentnode, we need to extract the result
ctx.rootContext.shouldDefineResult = true;
ctx.addLine(`result = []`);
ctx.addLine(`this.subTemplates['${subTemplate}'].call(this, ${callingScope}, Object.assign({}, extra, {parentNode: result}));`);
ctx.addLine(`this.subTemplates['${subTemplate}'].call(this, ${callingScope}, ${extra});`);
ctx.addLine(`result = result[0]`);
}
// Step 5: restore previous scope
@@ -2262,16 +2267,16 @@
const elems = node.getAttribute("t-foreach");
const name = node.getAttribute("t-as");
let arrayID = ctx.generateID();
ctx.addLine(`var _${arrayID} = ${ctx.formatExpression(elems)};`);
ctx.addLine(`let _${arrayID} = ${ctx.formatExpression(elems)};`);
ctx.addLine(`if (!_${arrayID}) { throw new Error('QWeb error: Invalid loop expression')}`);
let keysID = ctx.generateID();
let valuesID = ctx.generateID();
ctx.addLine(`var _${keysID} = _${valuesID} = _${arrayID};`);
ctx.addLine(`let _${keysID} = _${valuesID} = _${arrayID};`);
ctx.addIf(`!(_${arrayID} instanceof Array)`);
ctx.addLine(`_${keysID} = Object.keys(_${arrayID});`);
ctx.addLine(`_${valuesID} = Object.values(_${arrayID});`);
ctx.closeIf();
ctx.addLine(`var _length${keysID} = _${keysID}.length;`);
ctx.addLine(`let _length${keysID} = _${keysID}.length;`);
let varsID = ctx.startProtectScope();
const loopVar = `i${ctx.loopNumber}`;
ctx.addLine(`for (let ${loopVar} = 0; ${loopVar} < _length${keysID}; ${loopVar}++) {`);
@@ -2289,6 +2294,14 @@
if (shouldWarn) {
console.warn(`Directive t-foreach should always be used with a t-key! (in template: '${ctx.templateName}')`);
}
if (nodeCopy.hasAttribute("t-key")) {
const expr = ctx.formatExpression(nodeCopy.getAttribute("t-key"));
ctx.addLine(`let key${ctx.loopNumber} = ${expr};`);
nodeCopy.removeAttribute("t-key");
}
else {
ctx.addLine(`let key${ctx.loopNumber} = i${ctx.loopNumber};`);
}
nodeCopy.removeAttribute("t-foreach");
qweb._compileNode(nodeCopy, ctx);
ctx.dedent();
@@ -2317,8 +2330,8 @@
const expr = ctx.formatExpression(value);
ctx.addLine(`console.log(${expr})`);
}
});
});
/**
* Owl QWeb Extensions
*
@@ -2587,13 +2600,24 @@
QWeb.addDirective({
name: "key",
priority: 45,
atNodeEncounter({ ctx, value }) {
let id = ctx.generateID();
ctx.addLine(`const nodeKey${id} = ${ctx.formatExpression(value)};`);
ctx.currentKey = `nodeKey${id}`;
atNodeEncounter({ ctx, value, node }) {
if (ctx.loopNumber === 0) {
ctx.keyStack.push(ctx.rootContext.hasKey0);
ctx.rootContext.hasKey0 = true;
}
ctx.addLine("{");
ctx.indent();
ctx.addLine(`let key${ctx.loopNumber} = ${ctx.formatExpression(value)};`);
},
finalize({ ctx }) {
ctx.dedent();
ctx.addLine("}");
if (ctx.loopNumber === 0) {
ctx.rootContext.hasKey0 = ctx.keyStack.pop();
}
}
});
});
const config = {};
Object.defineProperty(config, "mode", {
get() {
@@ -2609,8 +2633,8 @@
console.log(`Owl is now running in 'prod' mode.`);
}
}
});
});
/**
* We define here OwlEvent, a subclass of CustomEvent, with an additional
* attribute:
@@ -2621,8 +2645,8 @@
super(eventType, options);
this.originalComponent = component;
}
}
}
//------------------------------------------------------------------------------
// t-component
//------------------------------------------------------------------------------
@@ -2829,7 +2853,7 @@
else if (!name.startsWith("t-")) {
if (name !== "class" && name !== "style") {
// this is a prop!
props[name] = ctx.formatExpression(value);
props[name] = ctx.formatExpression(value) || "undefined";
}
}
}
@@ -3004,8 +3028,8 @@
ctx.addLine(`w${componentID}.__owl__.parentLastFiberId = extra.fiber.id;`);
return true;
}
});
});
class Scheduler {
constructor(requestAnimationFrame) {
this.tasks = [];
@@ -3082,8 +3106,8 @@
}
}
const raf = window.requestAnimationFrame.bind(window);
const scheduler = new Scheduler(raf);
const scheduler = new Scheduler(raf);
/**
* Owl Fiber Class
*
@@ -3331,8 +3355,8 @@
}
}
}
Fiber.nextId = 1;
Fiber.nextId = 1;
//------------------------------------------------------------------------------
// Prop validation helper
//------------------------------------------------------------------------------
@@ -3446,8 +3470,61 @@
}
}
return result;
}
/**
* Owl Style System
*
* This files contains the Owl code related to processing (extended) css strings
* and creating/adding <style> tags to the document head.
*/
const STYLESHEETS = {};
function processSheet(str) {
const tokens = str.split(/(\{|\}|;)/).map(s => s.trim());
const selectorStack = [];
const parts = [];
let rules = [];
function generateRules() {
if (rules.length) {
parts.push(selectorStack.join(" ") + " {");
parts.push(...rules);
parts.push("}");
rules = [];
}
}
while (tokens.length) {
let token = tokens.shift();
if (token === "}") {
generateRules();
selectorStack.pop();
}
else {
if (tokens[0] === "{") {
generateRules();
selectorStack.push(token);
tokens.shift();
}
if (tokens[0] === ";") {
rules.push(" " + token + ";");
}
}
}
return parts.join("\n");
}
function registerSheet(id, css) {
const sheet = document.createElement("style");
sheet.innerHTML = processSheet(css);
STYLESHEETS[id] = sheet;
}
function activateSheet(id, name) {
const sheet = STYLESHEETS[id];
if (!sheet) {
throw new Error(`Invalid css stylesheet for component '${name}'. Did you forget to use the 'css' tag helper?`);
}
sheet.setAttribute("component", name);
document.head.appendChild(sheet);
}
const portalSymbol = Symbol("portal"); // FIXME
//------------------------------------------------------------------------------
// Component
@@ -3532,6 +3609,9 @@
refs: null,
scope: null
};
if (constr.style) {
this.__applyStyles(constr);
}
}
/**
* The `el` is the root element of the component. Note that it could be null:
@@ -3890,6 +3970,20 @@
this.__prepareAndRender(fiber, cb);
return fiber;
}
/**
* Apply the stylesheets defined by the component. Note that we need to make
* sure all inherited stylesheets are applied as well. We then delete the
* `style` key from the constructor to make sure we do not apply it again.
*/
__applyStyles(constr) {
while (constr && constr.style) {
if (constr.hasOwnProperty("style")) {
activateSheet(constr.style, constr.name);
delete constr.style;
}
constr = constr.__proto__;
}
}
__getTemplate(qweb) {
let p = this.constructor;
if (!p.hasOwnProperty("_template")) {
@@ -3999,8 +4093,8 @@
Component.components = {};
Component.env = {};
// expose scheduler s.t. it can be mocked for testing purposes
Component.scheduler = scheduler;
Component.scheduler = scheduler;
/**
* The `Context` object provides a way to share data between an arbitrary number
* of component. Usually, data is passed from a parent to its children component,
@@ -4135,8 +4229,8 @@
__destroy.call(component, parent);
};
return ctx.state;
}
}
/**
* Owl Hook System
*
@@ -4249,21 +4343,21 @@
function useSubEnv(nextEnv) {
const component = Component.current;
component.env = Object.assign(Object.create(component.env), nextEnv);
}
var _hooks = /*#__PURE__*/Object.freeze({
__proto__: null,
useState: useState,
onMounted: onMounted,
onWillUnmount: onWillUnmount,
onWillPatch: onWillPatch,
onPatched: onPatched,
onWillStart: onWillStart,
onWillUpdateProps: onWillUpdateProps,
useRef: useRef,
useSubEnv: useSubEnv
});
}
var _hooks = /*#__PURE__*/Object.freeze({
__proto__: null,
useState: useState,
onMounted: onMounted,
onWillUnmount: onWillUnmount,
onWillPatch: onWillPatch,
onPatched: onPatched,
onWillStart: onWillStart,
onWillUpdateProps: onWillUpdateProps,
useRef: useRef,
useSubEnv: useSubEnv
});
class Store extends Context {
constructor(config) {
super(config.state);
@@ -4342,7 +4436,7 @@
delete store.updateFunctions[componentId];
__destroy.call(component, parent);
};
if (typeof result !== "object") {
if (typeof result !== "object" || result === null) {
return result;
}
return new Proxy(result, {
@@ -4351,6 +4445,9 @@
},
set(target, k, v) {
throw new Error("Store state should only be modified through actions");
},
has(target, k) {
return k in result;
}
});
}
@@ -4361,8 +4458,8 @@
function useGetters(store) {
store = store || Component.current.env.store;
return store.getters;
}
}
/**
* Owl Tags
*
@@ -4387,12 +4484,28 @@
QWeb.registerTemplate(name, value);
return name;
}
var _tags = /*#__PURE__*/Object.freeze({
__proto__: null,
xml: xml
});
/**
* CSS tag helper for defining inline stylesheets. With this, one can simply define
* an inline stylesheet with just the following code:
* ```js
* class A extends Component {
* static style = css`.component-a { color: red; }`;
* }
* ```
*/
function css(strings, ...args) {
const name = `__sheet__${QWeb.nextId++}`;
const value = String.raw(strings, ...args);
registerSheet(name, value);
return name;
}
var _tags = /*#__PURE__*/Object.freeze({
__proto__: null,
xml: xml,
css: css
});
/**
* AsyncRoot
*
@@ -4406,8 +4519,8 @@
this.render(parentFiber.force);
}
}
AsyncRoot.template = xml `<t t-slot="default"/>`;
AsyncRoot.template = xml `<t t-slot="default"/>`;
/**
* Portal
*
@@ -4561,8 +4674,8 @@
target: {
type: String
}
};
};
class Link extends Component {
constructor() {
super(...arguments);
@@ -4603,8 +4716,8 @@
t-on-click="navigate">
<t t-slot="default"/>
</a>
`;
`;
class RouteComponent extends Component {
get routeComponent() {
return this.env.router.currentRoute && this.env.router.currentRoute.component;
@@ -4618,8 +4731,8 @@
t-key="env.router.currentRouteName"
t-props="env.router.currentParams" />
</t>
`;
`;
const paramRegexp = /\{\{(.*?)\}\}/;
class Router {
constructor(env, routes, options = { mode: "history" }) {
@@ -4821,8 +4934,8 @@
}
} while (m);
return result;
}
}
/**
* This file is the main file packaged by rollup (see rollup.config.js). From
* this file, we export all public owl elements.
@@ -4843,25 +4956,25 @@
useGetters: useGetters,
useStore: useStore
});
const __info__ = {};
exports.Component = Component;
exports.Context = Context$1;
exports.QWeb = QWeb;
exports.Store = Store$1;
exports.__info__ = __info__;
exports.config = config;
exports.core = core;
exports.hooks = hooks$1;
exports.misc = misc;
exports.router = router;
exports.tags = tags;
exports.useState = useState$1;
exports.utils = utils;
exports.__info__.version = '1.0.0-beta2';
exports.__info__.date = '2019-12-12T13:33:31.203Z';
exports.__info__.hash = '0931a4d';
exports.__info__.url = 'https://github.com/odoo/owl';
}(this.owl = this.owl || {}));
const __info__ = {};
exports.Component = Component;
exports.Context = Context$1;
exports.QWeb = QWeb;
exports.Store = Store$1;
exports.__info__ = __info__;
exports.config = config;
exports.core = core;
exports.hooks = hooks$1;
exports.misc = misc;
exports.router = router;
exports.tags = tags;
exports.useState = useState$1;
exports.utils = utils;
exports.__info__.version = '1.0.0-beta5';
exports.__info__.date = '2019-12-20T10:27:22.467Z';
exports.__info__.hash = 'b63cd4c';
exports.__info__.url = 'https://github.com/odoo/owl';
}(this.owl = this.owl || {}));
@@ -47,6 +47,7 @@ odoo.define('web.test_env', async function (require) {
const proxiedEnv = _proxify(env, 'env');
const defaultEnv = {
_t: env._t || (s => s),
_lt: env._lt || (s => s),
bus: new Bus(),
qweb: new owl.QWeb({ templates: session.owlTemplates }),
services: Object.assign({