[IMP] owl: update to v1.0.0-alpha3

This commit is contained in:
Géry Debongnie
2019-11-13 15:46:19 +01:00
parent 573e379af4
commit 4c2bb7c0fc
4 changed files with 48 additions and 74 deletions
+42 -13
View File
@@ -2953,7 +2953,7 @@
// hack: specify empty remove hook to prevent the node from being removed from the DOM // 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(`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(`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) { if (registerCode) {
ctx.addLine(registerCode); ctx.addLine(registerCode);
} }
@@ -3257,7 +3257,14 @@
break; 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) { if (!isValid) {
throw new Error(`Props '${propName}' of invalid type in component '${Widget.name}'`); throw new Error(`Props '${propName}' of invalid type in component '${Widget.name}'`);
} }
@@ -3297,6 +3304,9 @@
return result; return result;
} }
// propsDef is an object // propsDef is an object
if (propDef.optional && prop === undefined) {
return true;
}
let result = isValidProp(prop, propDef.type); let result = isValidProp(prop, propDef.type);
if (propDef.type === Array) { if (propDef.type === Array) {
for (let i = 0, iLen = prop.length; i < iLen; i++) { for (let i = 0, iLen = prop.length; i < iLen; i++) {
@@ -3308,6 +3318,13 @@
for (let key in shape) { for (let key in shape) {
result = result && isValidProp(prop[key], shape[key]); 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; return result;
} }
@@ -3478,17 +3495,15 @@
* *
* Note that a component can be mounted an unmounted several times * Note that a component can be mounted an unmounted several times
*/ */
async mount(target, renderBeforeRemount = false) { async mount(target) {
const __owl__ = this.__owl__; const __owl__ = this.__owl__;
if (__owl__.isMounted) { if (__owl__.isMounted) {
return Promise.resolve(); return Promise.resolve();
} }
if (__owl__.vnode && !renderBeforeRemount) { if (!(target instanceof HTMLElement)) {
target.appendChild(this.el); let message = `Component '${this.constructor.name}' cannot be mounted: the target is not a valid DOM node.`;
if (document.body.contains(target)) { message += `\nMaybe the DOM is not ready yet? (in that case, you can use owl.utils.whenReady)`;
this.__callMounted(); throw new Error(message);
}
return;
} }
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const fiber = new Fiber(null, this, undefined, undefined, false); const fiber = new Fiber(null, this, undefined, undefined, false);
@@ -3632,6 +3647,9 @@
} }
__owl__.isDestroyed = true; __owl__.isDestroyed = true;
delete __owl__.vnode; delete __owl__.vnode;
if (__owl__.currentFiber) {
__owl__.currentFiber.isCancelled = true;
}
} }
__callMounted() { __callMounted() {
const __owl__ = this.__owl__; const __owl__ = this.__owl__;
@@ -3838,6 +3856,8 @@
Component.current = null; Component.current = null;
Component.components = {}; Component.components = {};
Component.env = {}; Component.env = {};
// expose scheduler s.t. it can be mocked for testing purposes
Component.scheduler = scheduler;
/** /**
* Owl Hook System * Owl Hook System
@@ -3926,7 +3946,13 @@
return { return {
get el() { get el() {
const val = __owl__.refs && __owl__.refs[name]; 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() { get comp() {
const val = __owl__.refs && __owl__.refs[name]; const val = __owl__.refs && __owl__.refs[name];
@@ -4123,6 +4149,9 @@
function useStore(selector, options = {}) { function useStore(selector, options = {}) {
const component = Component.current; const component = Component.current;
const store = options.store || component.env.store; 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); let result = selector(store.state, component.props);
const hashFn = store.observer.revNumber.bind(store.observer); const hashFn = store.observer.revNumber.bind(store.observer);
let revNumber = hashFn(result) || result; let revNumber = hashFn(result) || result;
@@ -4515,9 +4544,9 @@
exports.useState = useState$1; exports.useState = useState$1;
exports.utils = utils; exports.utils = utils;
exports.__info__.version = '1.0.0-alpha2'; exports.__info__.version = '1.0.0-alpha3';
exports.__info__.date = '2019-11-01T08:12:51.280Z'; exports.__info__.date = '2019-11-13T14:44:19.699Z';
exports.__info__.hash = 'bd3c126'; exports.__info__.hash = 'd249f50';
exports.__info__.url = 'https://github.com/odoo/owl'; exports.__info__.url = 'https://github.com/odoo/owl';
}(this.owl = this.owl || {})); }(this.owl = this.owl || {}));
+6 -44
View File
@@ -70,13 +70,9 @@ if __name__ == "__main__":
/** /**
* Make an iframe, with all the js, css and xml properly injected. * Make an iframe, with all the js, css and xml properly injected.
*/ */
function makeCodeIframe(js, css, xml, errorHandler) { function makeCodeIframe(js, css, xml) {
// check templates
var qweb = new owl.QWeb();
const sanitizedXML = xml.replace(/<!--[\s\S]*?-->/g, ""); const sanitizedXML = xml.replace(/<!--[\s\S]*?-->/g, "");
// will throw error if there is something wrong with xml
qweb.addTemplates(sanitizedXML);
// create iframe // create iframe
const iframe = document.createElement("iframe"); const iframe = document.createElement("iframe");
@@ -92,21 +88,13 @@ function makeCodeIframe(js, css, xml, errorHandler) {
script.type = "text/javascript"; script.type = "text/javascript";
const content = ` const content = `
{ {
owl.__info__.mode = 'dev'; owl.config.mode = 'dev';
let templates = \`${sanitizedXML}\`; let templates = \`${sanitizedXML}\`;
const qweb = new owl.QWeb({ templates }); const qweb = new owl.QWeb({ templates });
owl.Component.env = { qweb }; owl.Component.env = { qweb };
} }
${js}`; ${js}`;
script.innerHTML = content; 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.body.appendChild(script);
}); });
doc.head.appendChild(owlScript); doc.head.appendChild(owlScript);
@@ -317,7 +305,6 @@ class App extends owl.Component {
js: this.SAMPLES[0].code, js: this.SAMPLES[0].code,
css: this.SAMPLES[0].css || "", css: this.SAMPLES[0].css || "",
xml: this.SAMPLES[0].xml || DEFAULT_XML, xml: this.SAMPLES[0].xml || DEFAULT_XML,
error: false,
displayWelcome: true, displayWelcome: true,
splitLayout: true, splitLayout: true,
leftPaneWidth: Math.ceil(window.innerWidth / 2), leftPaneWidth: Math.ceil(window.innerWidth / 2),
@@ -330,37 +317,12 @@ class App extends owl.Component {
this.content = useRef("content"); this.content = useRef("content");
} }
displayError(error) {
this.state.error = error;
if (error) {
setTimeout(() => {
this.content.el.innerHTML = "";
});
return;
}
}
runCode() { 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.content.el.innerHTML = "";
this.state.displayWelcome = false;
const { js, css, xml } = this.state;
const subiframe = makeCodeIframe(js, css, xml);
this.content.el.appendChild(subiframe); this.content.el.appendChild(subiframe);
} }
-13
View File
@@ -179,16 +179,3 @@ body {
padding: 5%; 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%;
}
-4
View File
@@ -51,10 +51,6 @@
</p> </p>
</div> </div>
</div> </div>
<div t-if="state.error" class="error">
<h3>Error</h3>
<pre t-esc="state.error"/>
</div>
<div class="content" t-ref="content"/> <div class="content" t-ref="content"/>
</div> </div>
</div> </div>