[FIX] web: update owl to last version
This commit updates owl from v1.0.9 to v1.0.10. See [1] for the list of fixes it contains. [1] https://github.com/odoo/owl/commit/e73fb462c5d70011ab667c1c529b85749a6bcf4a closes odoo/odoo#58959 X-original-commit: 1682c6b73c39c693e0fcdb4da70891ef55edc3fd Signed-off-by: Lucas Perais (lpe) <lpe@odoo.com>
This commit is contained in:
@@ -92,7 +92,10 @@
|
||||
}
|
||||
notifyCB() { }
|
||||
observe(value, parent) {
|
||||
if (value === null || typeof value !== "object" || value instanceof Date) {
|
||||
if (value === null ||
|
||||
typeof value !== "object" ||
|
||||
value instanceof Date ||
|
||||
value instanceof Promise) {
|
||||
// fun fact: typeof null === 'object'
|
||||
return value;
|
||||
}
|
||||
@@ -1358,7 +1361,6 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Const/global stuff/helpers
|
||||
//------------------------------------------------------------------------------
|
||||
const DISABLED_TAGS = ["input", "textarea", "button", "select", "option", "optgroup"];
|
||||
const TRANSLATABLE_ATTRS = ["label", "title", "placeholder", "alt"];
|
||||
const lineBreakRE = /[\r\n]/;
|
||||
const whitespaceRE = /\s+/g;
|
||||
@@ -1371,6 +1373,25 @@
|
||||
function isComponent(obj) {
|
||||
return obj && obj.hasOwnProperty("__owl__");
|
||||
}
|
||||
class VDomArray extends Array {
|
||||
toString() {
|
||||
return vDomToString(this);
|
||||
}
|
||||
}
|
||||
function vDomToString(vdom) {
|
||||
return vdom
|
||||
.map((vnode) => {
|
||||
if (vnode.sel) {
|
||||
const node = document.createElement(vnode.sel);
|
||||
const result = patch(node, vnode);
|
||||
return result.elm.outerHTML;
|
||||
}
|
||||
else {
|
||||
return vnode.text;
|
||||
}
|
||||
})
|
||||
.join("");
|
||||
}
|
||||
const UTILS = {
|
||||
zero: Symbol("zero"),
|
||||
toObj(expr) {
|
||||
@@ -1392,22 +1413,8 @@
|
||||
addNameSpace(vnode) {
|
||||
addNS(vnode.data, vnode.children, vnode.sel);
|
||||
},
|
||||
VDomArray: class VDomArray extends Array {
|
||||
},
|
||||
vDomToString: function (vdom) {
|
||||
return vdom
|
||||
.map((vnode) => {
|
||||
if (vnode.sel) {
|
||||
const node = document.createElement(vnode.sel);
|
||||
const result = patch(node, vnode);
|
||||
return result.elm.outerHTML;
|
||||
}
|
||||
else {
|
||||
return vnode.text;
|
||||
}
|
||||
})
|
||||
.join("");
|
||||
},
|
||||
VDomArray,
|
||||
vDomToString,
|
||||
getComponent(obj) {
|
||||
while (obj && !isComponent(obj)) {
|
||||
obj = obj.__proto__;
|
||||
@@ -1735,10 +1742,16 @@
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (node.tagName !== "t" && node.hasAttribute("t-call")) {
|
||||
const tCallNode = document.createElement("t");
|
||||
tCallNode.setAttribute("t-call", node.getAttribute("t-call"));
|
||||
node.removeAttribute("t-call");
|
||||
node.prepend(tCallNode);
|
||||
}
|
||||
const firstLetter = node.tagName[0];
|
||||
if (firstLetter === firstLetter.toUpperCase()) {
|
||||
// this is a component, we modify in place the xml document to change
|
||||
// <SomeComponent ... /> to <t t-component="SomeComponent" ... />
|
||||
// <SomeComponent ... /> to <SomeComponent t-component="SomeComponent" ... />
|
||||
node.setAttribute("t-component", node.tagName);
|
||||
}
|
||||
else if (node.tagName !== "t" && node.hasAttribute("t-component")) {
|
||||
@@ -1868,22 +1881,31 @@
|
||||
const attrs = [];
|
||||
const props = [];
|
||||
const tattrs = [];
|
||||
function handleBooleanProps(key, val) {
|
||||
function handleProperties(key, val) {
|
||||
let isProp = false;
|
||||
if (node.nodeName === "input" && key === "checked") {
|
||||
let type = node.getAttribute("type");
|
||||
if (type === "checkbox" || type === "radio") {
|
||||
isProp = true;
|
||||
}
|
||||
}
|
||||
if (node.nodeName === "option" && key === "selected") {
|
||||
isProp = true;
|
||||
}
|
||||
if (key === "disabled" && DISABLED_TAGS.indexOf(node.nodeName) > -1) {
|
||||
isProp = true;
|
||||
}
|
||||
if ((key === "readonly" && node.nodeName === "input") || node.nodeName === "textarea") {
|
||||
isProp = true;
|
||||
switch (node.nodeName) {
|
||||
case "input":
|
||||
let type = node.getAttribute("type");
|
||||
if (type === "checkbox" || type === "radio") {
|
||||
if (key === "checked" || key === "indeterminate") {
|
||||
isProp = true;
|
||||
}
|
||||
}
|
||||
if (key === "value" || key === "readonly" || key === "disabled") {
|
||||
isProp = true;
|
||||
}
|
||||
break;
|
||||
case "option":
|
||||
isProp = key === "selected" || key === "disabled";
|
||||
break;
|
||||
case "textarea":
|
||||
isProp = key === "readonly" || key === "disabled";
|
||||
break;
|
||||
case "button":
|
||||
case "select":
|
||||
case "optgroup":
|
||||
isProp = key === "disabled";
|
||||
break;
|
||||
}
|
||||
if (isProp) {
|
||||
props.push(`${key}: _${val}`);
|
||||
@@ -1921,7 +1943,7 @@
|
||||
name = '"' + name + '"';
|
||||
}
|
||||
attrs.push(`${name}: _${attID}`);
|
||||
handleBooleanProps(name, attID);
|
||||
handleProperties(name, attID);
|
||||
}
|
||||
}
|
||||
// dynamic attributes
|
||||
@@ -1958,7 +1980,7 @@
|
||||
}
|
||||
ctx.addLine(`let _${attID} = ${formattedValue};`);
|
||||
attrs.push(`${attName}: _${attID}`);
|
||||
handleBooleanProps(attName, attID);
|
||||
handleProperties(attName, attID);
|
||||
}
|
||||
}
|
||||
if (name.startsWith("t-attf-")) {
|
||||
@@ -2279,9 +2301,6 @@
|
||||
// ------------------------------------------------
|
||||
ctx.rootContext.shouldDefineScope = true;
|
||||
ctx.rootContext.shouldDefineUtils = true;
|
||||
if (node.nodeName !== "t") {
|
||||
throw new Error("Invalid tag for t-call directive (should be 't')");
|
||||
}
|
||||
const subTemplate = node.getAttribute("t-call");
|
||||
const nodeTemplate = qweb.templates[subTemplate];
|
||||
if (!nodeTemplate) {
|
||||
@@ -2299,12 +2318,11 @@
|
||||
// Step 3: compile t-call body if necessary
|
||||
// ------------------------------------------------
|
||||
let hasBody = node.hasChildNodes();
|
||||
let protectID;
|
||||
const protectID = ctx.startProtectScope();
|
||||
if (hasBody) {
|
||||
// we add a sub scope to protect the ambient scope
|
||||
ctx.addLine(`{`);
|
||||
ctx.indent();
|
||||
protectID = ctx.startProtectScope();
|
||||
const nodeCopy = node.cloneNode(true);
|
||||
for (let attr of ["t-if", "t-else", "t-elif", "t-call"]) {
|
||||
nodeCopy.removeAttribute(attr);
|
||||
@@ -2324,28 +2342,27 @@
|
||||
}
|
||||
// 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 key = ctx.generateTemplateKey();
|
||||
const parentNode = ctx.parentNode ? `c${ctx.parentNode}` : "result";
|
||||
const extra = `Object.assign({}, extra, {parentNode: ${parentNode}, parent: ${parentComponent}, key: ${key}})`;
|
||||
if (ctx.parentNode) {
|
||||
ctx.addLine(`this.constructor.subTemplates['${subId}'].call(this, ${callingScope}, ${extra});`);
|
||||
ctx.addLine(`this.constructor.subTemplates['${subId}'].call(this, scope, ${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.constructor.subTemplates['${subId}'].call(this, ${callingScope}, ${extra});`);
|
||||
ctx.addLine(`this.constructor.subTemplates['${subId}'].call(this, scope, ${extra});`);
|
||||
ctx.addLine(`result = result[0]`);
|
||||
}
|
||||
// Step 5: restore previous scope
|
||||
// ------------------------------------------------
|
||||
if (hasBody) {
|
||||
ctx.stopProtectScope(protectID);
|
||||
ctx.dedent();
|
||||
ctx.addLine(`}`);
|
||||
}
|
||||
ctx.stopProtectScope(protectID);
|
||||
return true;
|
||||
},
|
||||
});
|
||||
@@ -2653,6 +2670,8 @@
|
||||
const n = parseFloat(val);
|
||||
return isNaN(n) ? val : n;
|
||||
};
|
||||
const hasDotAtTheEnd = /\.[\w_]+\s*$/;
|
||||
const hasBracketsAtTheEnd = /\[[^\[]+\]\s*$/;
|
||||
QWeb.addDirective({
|
||||
name: "model",
|
||||
priority: 42,
|
||||
@@ -2660,14 +2679,41 @@
|
||||
const type = node.getAttribute("type");
|
||||
let handler;
|
||||
let event = fullName.includes(".lazy") ? "change" : "input";
|
||||
// we keep here a reference to the "base expression" (if the expression
|
||||
// is `t-model="some.expr.value", then the base expression is "some.expr").
|
||||
// This is necessary so we can capture it in the handler closure.
|
||||
let expr = ctx.formatExpression(value);
|
||||
const index = expr.lastIndexOf(".");
|
||||
const baseExpr = expr.slice(0, index);
|
||||
ctx.addLine(`let expr${nodeID} = ${baseExpr};`);
|
||||
expr = `expr${nodeID}.${expr.slice(index + 1)}`;
|
||||
// First step: we need to understand the structure of the expression, and
|
||||
// from it, extract a base expression (that we can capture, which is
|
||||
// important because it will be used in a handler later) and a formatted
|
||||
// expression (which uses the captured base expression)
|
||||
//
|
||||
// Also, we support 2 kinds of values: some.expr.value or some.expr[value]
|
||||
// For the first one, we have:
|
||||
// - base expression = scope[some].expr
|
||||
// - expression = exprX.value (where exprX is the var that captures the base expr)
|
||||
// and for the expression with brackets:
|
||||
// - base expression = scope[some].expr
|
||||
// - expression = exprX[keyX] (where exprX is the var that captures the base expr
|
||||
// and keyX captures scope[value])
|
||||
let expr;
|
||||
let baseExpr;
|
||||
if (hasDotAtTheEnd.test(value)) {
|
||||
// we manage the case where the expr has a dot: some.expr.value
|
||||
const index = value.lastIndexOf(".");
|
||||
baseExpr = value.slice(0, index);
|
||||
ctx.addLine(`let expr${nodeID} = ${ctx.formatExpression(baseExpr)};`);
|
||||
expr = `expr${nodeID}${value.slice(index)}`;
|
||||
}
|
||||
else if (hasBracketsAtTheEnd.test(value)) {
|
||||
// we manage here the case where the expr ends in a bracket expression:
|
||||
// some.expr[value]
|
||||
const index = value.lastIndexOf("[");
|
||||
baseExpr = value.slice(0, index);
|
||||
ctx.addLine(`let expr${nodeID} = ${ctx.formatExpression(baseExpr)};`);
|
||||
let exprKey = value.trimRight().slice(index + 1, -1);
|
||||
ctx.addLine(`let exprKey${nodeID} = ${ctx.formatExpression(exprKey)};`);
|
||||
expr = `expr${nodeID}[exprKey${nodeID}]`;
|
||||
}
|
||||
else {
|
||||
throw new Error(`Invalid t-model expression: "${value}" (it should be assignable)`);
|
||||
}
|
||||
const key = ctx.generateTemplateKey();
|
||||
if (node.tagName === "select") {
|
||||
ctx.addLine(`p${nodeID}.props = {value: ${expr}};`);
|
||||
@@ -3465,13 +3511,21 @@
|
||||
else {
|
||||
if (fiber.shouldPatch) {
|
||||
component.__patch(component.__owl__.vnode, fiber.vnode);
|
||||
// When updating a Component's props (in directive),
|
||||
// the component has a pvnode AND should be patched.
|
||||
// However, its pvnode.elm may have changed if it is a High Order Component
|
||||
if (component.__owl__.pvnode) {
|
||||
component.__owl__.pvnode.elm = component.__owl__.vnode.elm;
|
||||
}
|
||||
}
|
||||
else {
|
||||
component.__patch(document.createElement(fiber.vnode.sel), fiber.vnode);
|
||||
component.__owl__.pvnode.elm = component.__owl__.vnode.elm;
|
||||
}
|
||||
}
|
||||
component.__owl__.currentFiber = null;
|
||||
if (fiber === component.__owl__.currentFiber) {
|
||||
component.__owl__.currentFiber = null;
|
||||
}
|
||||
}
|
||||
// insert into the DOM (mount case)
|
||||
let inDOM = false;
|
||||
@@ -3585,7 +3639,7 @@
|
||||
throw new Error(`Missing props '${propName}' (component '${Widget.name}')`);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let isValid;
|
||||
@@ -4092,9 +4146,9 @@
|
||||
}
|
||||
this.willUnmount();
|
||||
__owl__.isMounted = false;
|
||||
if (this.__owl__.currentFiber) {
|
||||
this.__owl__.currentFiber.isCompleted = true;
|
||||
this.__owl__.currentFiber.root.counter = 0;
|
||||
if (__owl__.currentFiber) {
|
||||
__owl__.currentFiber.isCompleted = true;
|
||||
__owl__.currentFiber.root.counter = 0;
|
||||
}
|
||||
const children = __owl__.children;
|
||||
for (let id in children) {
|
||||
@@ -4249,9 +4303,28 @@
|
||||
// destroyed right now, because they are not in the DOM, and thus we won't
|
||||
// be notified later on (when patching), that they are removed from the DOM
|
||||
for (let childKey in __owl__.children) {
|
||||
let child = __owl__.children[childKey];
|
||||
if (!child.__owl__.isMounted && child.__owl__.parentLastFiberId < fiber.id) {
|
||||
child.destroy();
|
||||
const child = __owl__.children[childKey];
|
||||
const childOwl = child.__owl__;
|
||||
if (!childOwl.isMounted && childOwl.parentLastFiberId < fiber.id) {
|
||||
// we only do here a "soft" destroy, meaning that we leave the child
|
||||
// dom node alone, without removing it. Most of the time, it does not
|
||||
// matter, because the child component is already unmounted. However,
|
||||
// if some of its parent have been unmounted, the child could actually
|
||||
// still be attached to its parent, and this may be important if we
|
||||
// want to remount the parent, because the vdom need to match the
|
||||
// actual DOM
|
||||
child.__destroy(childOwl.parent);
|
||||
if (childOwl.pvnode) {
|
||||
// we remove the key here to make sure that the patching algorithm
|
||||
// is able to make the difference between this pvnode and an eventual
|
||||
// other instance of the same component
|
||||
delete childOwl.pvnode.key;
|
||||
// Since the component has been unmounted, we do not want to actually
|
||||
// call a remove hook. This is pretty important, since the t-component
|
||||
// directive actually disabled it, so the vdom algorithm will just
|
||||
// not remove the child elm if we don't remove the hook.
|
||||
delete childOwl.pvnode.data.hook.remove;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!vnode) {
|
||||
@@ -5195,9 +5268,9 @@
|
||||
exports.useState = useState$1;
|
||||
exports.utils = utils;
|
||||
|
||||
exports.__info__.version = '1.0.9';
|
||||
exports.__info__.date = '2020-06-09T06:36:43.187Z';
|
||||
exports.__info__.hash = 'c5a2f52';
|
||||
exports.__info__.version = '1.0.10';
|
||||
exports.__info__.date = '2020-10-02T07:33:29.701Z';
|
||||
exports.__info__.hash = 'e73fb46';
|
||||
exports.__info__.url = 'https://github.com/odoo/owl';
|
||||
|
||||
}(this.owl = this.owl || {}));
|
||||
|
||||
Reference in New Issue
Block a user