From 4c2bb7c0fc85531637011fb0bddeaab53ef4203c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=A9ry=20Debongnie?=
Date: Wed, 13 Nov 2019 15:46:19 +0100
Subject: [PATCH] [IMP] owl: update to v1.0.0-alpha3
---
owl.js | 55 ++++++++++++++++++++++++++++++---------
playground/app.js | 50 +++++------------------------------
playground/playground.css | 13 ---------
playground/templates.xml | 4 ---
4 files changed, 48 insertions(+), 74 deletions(-)
diff --git a/owl.js b/owl.js
index b4dc701f..4d99e2a6 100644
--- a/owl.js
+++ b/owl.js
@@ -2953,7 +2953,7 @@
// hack: specify empty remove hook to prevent the node from being removed from the DOM
ctx.addLine(`let pvnode = h('dummy', {key: ${templateId}, hook: {insert(vn) { let nvn=w${componentID}.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;${refExpr}${transitionsInsertCode}},remove() {},destroy(vn) {${finalizeComponentCode}}}});`);
ctx.addLine(`const fiber = w${componentID}.__owl__.currentFiber;`);
- ctx.addLine(`def${defID}.then(function () {if (w${componentID}.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; ${createHook}});`);
+ ctx.addLine(`def${defID}.then(function () {if (fiber.isCancelled) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; ${createHook}});`);
if (registerCode) {
ctx.addLine(registerCode);
}
@@ -3257,7 +3257,14 @@
break;
}
}
- let isValid = isValidProp(props[propName], propsDef[propName]);
+ let isValid;
+ try {
+ isValid = isValidProp(props[propName], propsDef[propName]);
+ }
+ catch (e) {
+ e.message = `Invalid prop '${propName}' in component ${Widget.name} (${e.message})`;
+ throw e;
+ }
if (!isValid) {
throw new Error(`Props '${propName}' of invalid type in component '${Widget.name}'`);
}
@@ -3297,6 +3304,9 @@
return result;
}
// propsDef is an object
+ if (propDef.optional && prop === undefined) {
+ return true;
+ }
let result = isValidProp(prop, propDef.type);
if (propDef.type === Array) {
for (let i = 0, iLen = prop.length; i < iLen; i++) {
@@ -3308,6 +3318,13 @@
for (let key in shape) {
result = result && isValidProp(prop[key], shape[key]);
}
+ if (result) {
+ for (let propName in prop) {
+ if (!(propName in shape)) {
+ throw new Error(`unknown prop '${propName}'`);
+ }
+ }
+ }
}
return result;
}
@@ -3478,17 +3495,15 @@
*
* Note that a component can be mounted an unmounted several times
*/
- async mount(target, renderBeforeRemount = false) {
+ async mount(target) {
const __owl__ = this.__owl__;
if (__owl__.isMounted) {
return Promise.resolve();
}
- if (__owl__.vnode && !renderBeforeRemount) {
- target.appendChild(this.el);
- if (document.body.contains(target)) {
- this.__callMounted();
- }
- return;
+ if (!(target instanceof HTMLElement)) {
+ let message = `Component '${this.constructor.name}' cannot be mounted: the target is not a valid DOM node.`;
+ message += `\nMaybe the DOM is not ready yet? (in that case, you can use owl.utils.whenReady)`;
+ throw new Error(message);
}
return new Promise((resolve, reject) => {
const fiber = new Fiber(null, this, undefined, undefined, false);
@@ -3632,6 +3647,9 @@
}
__owl__.isDestroyed = true;
delete __owl__.vnode;
+ if (__owl__.currentFiber) {
+ __owl__.currentFiber.isCancelled = true;
+ }
}
__callMounted() {
const __owl__ = this.__owl__;
@@ -3838,6 +3856,8 @@
Component.current = null;
Component.components = {};
Component.env = {};
+ // expose scheduler s.t. it can be mocked for testing purposes
+ Component.scheduler = scheduler;
/**
* Owl Hook System
@@ -3926,7 +3946,13 @@
return {
get el() {
const val = __owl__.refs && __owl__.refs[name];
- return val instanceof HTMLElement ? val : null;
+ if (val instanceof HTMLElement) {
+ return val;
+ }
+ else if (val instanceof Component) {
+ return val.el;
+ }
+ return null;
},
get comp() {
const val = __owl__.refs && __owl__.refs[name];
@@ -4123,6 +4149,9 @@
function useStore(selector, options = {}) {
const component = Component.current;
const store = options.store || component.env.store;
+ if (!(store instanceof Store)) {
+ throw new Error(`No store found when connecting '${component.constructor.name}'`);
+ }
let result = selector(store.state, component.props);
const hashFn = store.observer.revNumber.bind(store.observer);
let revNumber = hashFn(result) || result;
@@ -4515,9 +4544,9 @@
exports.useState = useState$1;
exports.utils = utils;
- exports.__info__.version = '1.0.0-alpha2';
- exports.__info__.date = '2019-11-01T08:12:51.280Z';
- exports.__info__.hash = 'bd3c126';
+ exports.__info__.version = '1.0.0-alpha3';
+ exports.__info__.date = '2019-11-13T14:44:19.699Z';
+ exports.__info__.hash = 'd249f50';
exports.__info__.url = 'https://github.com/odoo/owl';
}(this.owl = this.owl || {}));
diff --git a/playground/app.js b/playground/app.js
index d07ca6ec..f4d841fc 100644
--- a/playground/app.js
+++ b/playground/app.js
@@ -70,13 +70,9 @@ if __name__ == "__main__":
/**
* Make an iframe, with all the js, css and xml properly injected.
*/
-function makeCodeIframe(js, css, xml, errorHandler) {
- // check templates
- var qweb = new owl.QWeb();
+function makeCodeIframe(js, css, xml) {
const sanitizedXML = xml.replace(//g, "");
- // will throw error if there is something wrong with xml
- qweb.addTemplates(sanitizedXML);
// create iframe
const iframe = document.createElement("iframe");
@@ -92,21 +88,13 @@ function makeCodeIframe(js, css, xml, errorHandler) {
script.type = "text/javascript";
const content = `
{
- owl.__info__.mode = 'dev';
+ owl.config.mode = 'dev';
let templates = \`${sanitizedXML}\`;
const qweb = new owl.QWeb({ templates });
owl.Component.env = { qweb };
}
${js}`;
script.innerHTML = content;
- iframe.contentWindow.addEventListener("error", errorHandler);
- iframe.contentWindow.addEventListener("unhandledrejection", errorHandler);
- setTimeout(function() {
- if (iframe.contentWindow) {
- iframe.contentWindow.removeEventListener("error", errorHandler);
- iframe.contentWindow.removeEventListener("unhandledrejection", errorHandler);
- }
- }, 200);
doc.body.appendChild(script);
});
doc.head.appendChild(owlScript);
@@ -317,7 +305,6 @@ class App extends owl.Component {
js: this.SAMPLES[0].code,
css: this.SAMPLES[0].css || "",
xml: this.SAMPLES[0].xml || DEFAULT_XML,
- error: false,
displayWelcome: true,
splitLayout: true,
leftPaneWidth: Math.ceil(window.innerWidth / 2),
@@ -330,37 +317,12 @@ class App extends owl.Component {
this.content = useRef("content");
}
- displayError(error) {
- this.state.error = error;
- if (error) {
- setTimeout(() => {
- this.content.el.innerHTML = "";
- });
- return;
- }
- }
-
runCode() {
- this.state.displayWelcome = false;
- let subiframe;
- let error = false;
- const errorHandler = e => this.displayError(e.message || e.reason.message);
- try {
- const { js, css, xml } = this.state;
- subiframe = makeCodeIframe(js, css, xml, errorHandler);
- } catch (e) {
- //probably problem with the templates
- error = e;
- // we still log the error, always useful to have it available
- console.error(e);
- }
- if (error) {
- this.displayError(error.message);
- return;
- } else {
- this.state.error = false;
- }
this.content.el.innerHTML = "";
+ this.state.displayWelcome = false;
+
+ const { js, css, xml } = this.state;
+ const subiframe = makeCodeIframe(js, css, xml);
this.content.el.appendChild(subiframe);
}
diff --git a/playground/playground.css b/playground/playground.css
index 5c469019..bff9db39 100644
--- a/playground/playground.css
+++ b/playground/playground.css
@@ -179,16 +179,3 @@ body {
padding: 5%;
}
-.right-pane .error {
- height: 100%;
- width: 90%;
- padding-top: 30%;
- font-size: 18px;
- color: darkred;
- margin-left: 5%;
-}
-
-.right-pane .error pre {
- overflow: auto;
- width: 100%;
-}
diff --git a/playground/templates.xml b/playground/templates.xml
index b42bd715..c0c1300a 100644
--- a/playground/templates.xml
+++ b/playground/templates.xml
@@ -51,10 +51,6 @@
-