mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[IMP] owl: update library
This commit is contained in:
+254
-142
@@ -857,12 +857,12 @@
|
|||||||
if (parent instanceof Component) {
|
if (parent instanceof Component) {
|
||||||
p = parent;
|
p = parent;
|
||||||
this.env = parent.env;
|
this.env = parent.env;
|
||||||
parent.__widget__.children[id] = this;
|
parent.__owl__.children[id] = this;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.env = parent;
|
this.env = parent;
|
||||||
}
|
}
|
||||||
this.__widget__ = {
|
this.__owl__ = {
|
||||||
id: id,
|
id: id,
|
||||||
vnode: null,
|
vnode: null,
|
||||||
isStarted: false,
|
isStarted: false,
|
||||||
@@ -878,7 +878,7 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
get el() {
|
get el() {
|
||||||
return this.__widget__.vnode ? this.__widget__.vnode.elm : null;
|
return this.__owl__.vnode ? this.__owl__.vnode.elm : null;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* willStart is an asynchronous hook that can be implemented to perform some
|
* willStart is an asynchronous hook that can be implemented to perform some
|
||||||
@@ -971,7 +971,7 @@
|
|||||||
}
|
}
|
||||||
async mount(target) {
|
async mount(target) {
|
||||||
const vnode = await this._prepare();
|
const vnode = await this._prepare();
|
||||||
if (this.__widget__.isDestroyed) {
|
if (this.__owl__.isDestroyed) {
|
||||||
// widget was destroyed before we get here...
|
// widget was destroyed before we get here...
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -979,8 +979,8 @@
|
|||||||
target.appendChild(this.el);
|
target.appendChild(this.el);
|
||||||
if (document.body.contains(target)) {
|
if (document.body.contains(target)) {
|
||||||
this._visitSubTree(w => {
|
this._visitSubTree(w => {
|
||||||
if (!w.__widget__.isMounted && this.el.contains(w.el)) {
|
if (!w.__owl__.isMounted && this.el.contains(w.el)) {
|
||||||
w.__widget__.isMounted = true;
|
w.__owl__.isMounted = true;
|
||||||
w.mounted();
|
w.mounted();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -991,9 +991,9 @@
|
|||||||
unmount() {
|
unmount() {
|
||||||
if (this.el) {
|
if (this.el) {
|
||||||
this._visitSubTree(w => {
|
this._visitSubTree(w => {
|
||||||
if (w.__widget__.isMounted) {
|
if (w.__owl__.isMounted) {
|
||||||
w.willUnmount();
|
w.willUnmount();
|
||||||
w.__widget__.isMounted = false;
|
w.__owl__.isMounted = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -1002,38 +1002,38 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
async render(force = false) {
|
async render(force = false) {
|
||||||
if (this.__widget__.isDestroyed) {
|
if (this.__owl__.isDestroyed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const renderVDom = this._render(force);
|
const renderVDom = this._render(force);
|
||||||
const renderId = this.__widget__.renderId;
|
const renderId = this.__owl__.renderId;
|
||||||
const vnode = await renderVDom;
|
const vnode = await renderVDom;
|
||||||
if (renderId === this.__widget__.renderId) {
|
if (renderId === this.__owl__.renderId) {
|
||||||
// we only update the vnode and the actual DOM if no other rendering
|
// we only update the vnode and the actual DOM if no other rendering
|
||||||
// occurred between now and when the render method was initially called.
|
// occurred between now and when the render method was initially called.
|
||||||
this._patch(vnode);
|
this._patch(vnode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
destroy() {
|
destroy() {
|
||||||
if (!this.__widget__.isDestroyed) {
|
if (!this.__owl__.isDestroyed) {
|
||||||
for (let id in this.__widget__.children) {
|
for (let id in this.__owl__.children) {
|
||||||
this.__widget__.children[id].destroy();
|
this.__owl__.children[id].destroy();
|
||||||
}
|
}
|
||||||
if (this.__widget__.isMounted) {
|
if (this.__owl__.isMounted) {
|
||||||
this.willUnmount();
|
this.willUnmount();
|
||||||
}
|
}
|
||||||
if (this.el) {
|
if (this.el) {
|
||||||
this.el.remove();
|
this.el.remove();
|
||||||
this.__widget__.isMounted = false;
|
this.__owl__.isMounted = false;
|
||||||
delete this.__widget__.vnode;
|
delete this.__owl__.vnode;
|
||||||
}
|
}
|
||||||
if (this.__widget__.parent) {
|
if (this.__owl__.parent) {
|
||||||
let id = this.__widget__.id;
|
let id = this.__owl__.id;
|
||||||
delete this.__widget__.parent.__widget__.children[id];
|
delete this.__owl__.parent.__owl__.children[id];
|
||||||
this.__widget__.parent = null;
|
this.__owl__.parent = null;
|
||||||
}
|
}
|
||||||
this.clear();
|
this.clear();
|
||||||
this.__widget__.isDestroyed = true;
|
this.__owl__.isDestroyed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
shouldUpdate(nextProps) {
|
shouldUpdate(nextProps) {
|
||||||
@@ -1049,20 +1049,16 @@
|
|||||||
* mode or not.
|
* mode or not.
|
||||||
*/
|
*/
|
||||||
async updateEnv(nextEnv) {
|
async updateEnv(nextEnv) {
|
||||||
if (this.__widget__.parent && this.__widget__.parent.env === this.env) {
|
if (this.__owl__.parent && this.__owl__.parent.env === this.env) {
|
||||||
this.env = Object.create(this.env);
|
this.env = Object.create(this.env);
|
||||||
}
|
}
|
||||||
Object.assign(this.env, nextEnv);
|
Object.assign(this.env, nextEnv);
|
||||||
if (this.__widget__.isMounted) {
|
if (this.__owl__.isMounted) {
|
||||||
await this.render(true);
|
await this.render(true);
|
||||||
}
|
}
|
||||||
this.patched();
|
this.patched();
|
||||||
}
|
}
|
||||||
async updateProps(nextProps, forceUpdate = false) {
|
async updateProps(nextProps, forceUpdate = false) {
|
||||||
if (nextProps === this.__widget__.renderProps && !forceUpdate) {
|
|
||||||
await this.__widget__.renderPromise;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const shouldUpdate = forceUpdate || this.shouldUpdate(nextProps);
|
const shouldUpdate = forceUpdate || this.shouldUpdate(nextProps);
|
||||||
return shouldUpdate ? this._updateProps(nextProps) : Promise.resolve();
|
return shouldUpdate ? this._updateProps(nextProps) : Promise.resolve();
|
||||||
}
|
}
|
||||||
@@ -1080,7 +1076,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Object.assign(this.state, nextState);
|
Object.assign(this.state, nextState);
|
||||||
if (this.__widget__.isStarted) {
|
if (this.__owl__.isStarted) {
|
||||||
await this.render();
|
await this.render();
|
||||||
}
|
}
|
||||||
this.patched();
|
this.patched();
|
||||||
@@ -1095,36 +1091,36 @@
|
|||||||
this.patched();
|
this.patched();
|
||||||
}
|
}
|
||||||
_patch(vnode) {
|
_patch(vnode) {
|
||||||
this.__widget__.renderPromise = null;
|
this.__owl__.renderPromise = null;
|
||||||
if (this.__widget__.vnode) {
|
if (this.__owl__.vnode) {
|
||||||
this.willPatch();
|
this.willPatch();
|
||||||
this.__widget__.vnode = patch$1(this.__widget__.vnode, vnode);
|
this.__owl__.vnode = patch$1(this.__owl__.vnode, vnode);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.__widget__.vnode = patch$1(document.createElement(vnode.sel), vnode);
|
this.__owl__.vnode = patch$1(document.createElement(vnode.sel), vnode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async _prepare() {
|
async _prepare() {
|
||||||
this.__widget__.renderProps = this.props;
|
this.__owl__.renderProps = this.props;
|
||||||
this.__widget__.renderPromise = this.willStart().then(() => {
|
this.__owl__.renderPromise = this.willStart().then(() => {
|
||||||
if (this.__widget__.isDestroyed) {
|
if (this.__owl__.isDestroyed) {
|
||||||
return Promise.resolve(h("div"));
|
return Promise.resolve(h("div"));
|
||||||
}
|
}
|
||||||
this.__widget__.isStarted = true;
|
this.__owl__.isStarted = true;
|
||||||
if (this.inlineTemplate) {
|
if (this.inlineTemplate) {
|
||||||
this.env.qweb.addTemplate(this.inlineTemplate, this.inlineTemplate, true);
|
this.env.qweb.addTemplate(this.inlineTemplate, this.inlineTemplate, true);
|
||||||
}
|
}
|
||||||
return this._render();
|
return this._render();
|
||||||
});
|
});
|
||||||
return this.__widget__.renderPromise;
|
return this.__owl__.renderPromise;
|
||||||
}
|
}
|
||||||
async _render(force = false) {
|
async _render(force = false) {
|
||||||
this.__widget__.renderId++;
|
this.__owl__.renderId++;
|
||||||
const promises = [];
|
const promises = [];
|
||||||
const template = this.inlineTemplate || this.template;
|
const template = this.inlineTemplate || this.template;
|
||||||
let vnode = this.env.qweb.render(template, this, {
|
let vnode = this.env.qweb.render(template, this, {
|
||||||
promises,
|
promises,
|
||||||
handlers: this.__widget__.boundHandlers,
|
handlers: this.__owl__.boundHandlers,
|
||||||
forceUpdate: force
|
forceUpdate: force
|
||||||
});
|
});
|
||||||
// this part is critical for the patching process to be done correctly. The
|
// this part is critical for the patching process to be done correctly. The
|
||||||
@@ -1132,28 +1128,28 @@
|
|||||||
// will update its own vnode representation without the knowledge of the
|
// will update its own vnode representation without the knowledge of the
|
||||||
// parent widget. With this, we make sure that the parent widget will be
|
// parent widget. With this, we make sure that the parent widget will be
|
||||||
// able to patch itself properly after
|
// able to patch itself properly after
|
||||||
vnode.key = this.__widget__.id;
|
vnode.key = this.__owl__.id;
|
||||||
this.__widget__.renderProps = this.props;
|
this.__owl__.renderProps = this.props;
|
||||||
this.__widget__.renderPromise = Promise.all(promises).then(() => vnode);
|
this.__owl__.renderPromise = Promise.all(promises).then(() => vnode);
|
||||||
return this.__widget__.renderPromise;
|
return this.__owl__.renderPromise;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Only called by qweb t-widget directive
|
* Only called by qweb t-widget directive
|
||||||
*/
|
*/
|
||||||
_mount(vnode, elm) {
|
_mount(vnode, elm) {
|
||||||
this.__widget__.vnode = patch$1(elm, vnode);
|
this.__owl__.vnode = patch$1(elm, vnode);
|
||||||
this.__mount();
|
this.__mount();
|
||||||
return this.__widget__.vnode;
|
return this.__owl__.vnode;
|
||||||
}
|
}
|
||||||
__mount() {
|
__mount() {
|
||||||
if (this.__widget__.isMounted) {
|
if (this.__owl__.isMounted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.__widget__.parent) {
|
if (this.__owl__.parent) {
|
||||||
if (this.__widget__.parent.__widget__.isMounted) {
|
if (this.__owl__.parent.__owl__.isMounted) {
|
||||||
this.__widget__.isMounted = true;
|
this.__owl__.isMounted = true;
|
||||||
this.mounted();
|
this.mounted();
|
||||||
const children = this.__widget__.children;
|
const children = this.__owl__.children;
|
||||||
for (let id in children) {
|
for (let id in children) {
|
||||||
children[id].__mount();
|
children[id].__mount();
|
||||||
}
|
}
|
||||||
@@ -1163,7 +1159,7 @@
|
|||||||
_visitSubTree(callback) {
|
_visitSubTree(callback) {
|
||||||
const shouldVisitChildren = callback(this);
|
const shouldVisitChildren = callback(this);
|
||||||
if (shouldVisitChildren) {
|
if (shouldVisitChildren) {
|
||||||
const children = this.__widget__.children;
|
const children = this.__owl__.children;
|
||||||
for (let id in children) {
|
for (let id in children) {
|
||||||
children[id]._visitSubTree(callback);
|
children[id]._visitSubTree(callback);
|
||||||
}
|
}
|
||||||
@@ -1215,6 +1211,7 @@
|
|||||||
this.nextID = 1;
|
this.nextID = 1;
|
||||||
this.code = [];
|
this.code = [];
|
||||||
this.variables = {};
|
this.variables = {};
|
||||||
|
this.definedVariables = {};
|
||||||
this.escaping = false;
|
this.escaping = false;
|
||||||
this.parentNode = null;
|
this.parentNode = null;
|
||||||
this.rootNode = null;
|
this.rootNode = null;
|
||||||
@@ -1315,11 +1312,13 @@
|
|||||||
else if (c.match(/\W/) && invar.length) {
|
else if (c.match(/\W/) && invar.length) {
|
||||||
// TODO: Should check for possible spaces before dot
|
// TODO: Should check for possible spaces before dot
|
||||||
if (chars[invarPos - 1] !== "." && RESERVED_WORDS.indexOf(invar) < 0) {
|
if (chars[invarPos - 1] !== "." && RESERVED_WORDS.indexOf(invar) < 0) {
|
||||||
invar =
|
if (!(invar in this.definedVariables)) {
|
||||||
WORD_REPLACEMENT[invar] ||
|
invar =
|
||||||
(invar in this.variables &&
|
WORD_REPLACEMENT[invar] ||
|
||||||
this.formatExpression(this.variables[invar])) ||
|
(invar in this.variables &&
|
||||||
"context['" + invar + "']";
|
this.formatExpression(this.variables[invar])) ||
|
||||||
|
"context['" + invar + "']";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
r += invar;
|
r += invar;
|
||||||
invar = "";
|
invar = "";
|
||||||
@@ -1359,6 +1358,17 @@
|
|||||||
return classes.join(" ");
|
return classes.join(" ");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
this.directiveNames = {
|
||||||
|
as: 1,
|
||||||
|
name: 1,
|
||||||
|
value: 1,
|
||||||
|
att: 1,
|
||||||
|
attf: 1,
|
||||||
|
props: 1,
|
||||||
|
key: 1,
|
||||||
|
keepalive: 1,
|
||||||
|
debug: 1
|
||||||
|
};
|
||||||
[
|
[
|
||||||
forEachDirective,
|
forEachDirective,
|
||||||
escDirective,
|
escDirective,
|
||||||
@@ -1378,6 +1388,7 @@
|
|||||||
}
|
}
|
||||||
addDirective(dir) {
|
addDirective(dir) {
|
||||||
this.directives.push(dir);
|
this.directives.push(dir);
|
||||||
|
this.directiveNames[dir.name] = 1;
|
||||||
this.directives.sort((d1, d2) => d1.priority - d2.priority);
|
this.directives.sort((d1, d2) => d1.priority - d2.priority);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -1538,8 +1549,18 @@
|
|||||||
const attributes = node.attributes;
|
const attributes = node.attributes;
|
||||||
const validDirectives = [];
|
const validDirectives = [];
|
||||||
let withHandlers = false;
|
let withHandlers = false;
|
||||||
|
// maybe this is not optimal: we iterate on all attributes here, and again
|
||||||
|
// just after for each directive.
|
||||||
|
for (let i = 0; i < attributes.length; i++) {
|
||||||
|
let attrName = attributes[i].name;
|
||||||
|
if (attrName.startsWith("t-")) {
|
||||||
|
let dName = attrName.slice(2).split("-")[0];
|
||||||
|
if (!(dName in this.directiveNames)) {
|
||||||
|
throw new Error(`Unknown QWeb directive: '${attrName}'`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
for (let directive of this.directives) {
|
for (let directive of this.directives) {
|
||||||
// const value = attributes[i].textContent!;
|
|
||||||
let fullName;
|
let fullName;
|
||||||
let value;
|
let value;
|
||||||
for (let i = 0; i < attributes.length; i++) {
|
for (let i = 0; i < attributes.length; i++) {
|
||||||
@@ -1735,19 +1756,21 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (typeof value === "string") {
|
if (typeof value === "string") {
|
||||||
const exprID = ctx.generateID();
|
let exprID = value;
|
||||||
ctx.addLine(`var e${exprID} = ${ctx.formatExpression(value)};`);
|
if (!(value in ctx.definedVariables)) {
|
||||||
ctx.addIf(`e${exprID} || e${exprID} === 0`);
|
exprID = `_${ctx.generateID()}`;
|
||||||
let text = `e${exprID}`;
|
ctx.addLine(`var ${exprID} = ${ctx.formatExpression(value)};`);
|
||||||
|
}
|
||||||
|
ctx.addIf(`${exprID} || ${exprID} === 0`);
|
||||||
if (!ctx.parentNode) {
|
if (!ctx.parentNode) {
|
||||||
throw new Error("Should not have a text node without a parent");
|
throw new Error("Should not have a text node without a parent");
|
||||||
}
|
}
|
||||||
if (ctx.escaping) {
|
if (ctx.escaping) {
|
||||||
ctx.addLine(`c${ctx.parentNode}.push({text: ${text}});`);
|
ctx.addLine(`c${ctx.parentNode}.push({text: ${exprID}});`);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let fragID = ctx.generateID();
|
let fragID = ctx.generateID();
|
||||||
ctx.addLine(`var frag${fragID} = this.utils.getFragment(e${exprID})`);
|
ctx.addLine(`var frag${fragID} = this.utils.getFragment(${exprID})`);
|
||||||
let tempNodeID = ctx.generateID();
|
let tempNodeID = ctx.generateID();
|
||||||
ctx.addLine(`var p${tempNodeID} = {hook: {`);
|
ctx.addLine(`var p${tempNodeID} = {hook: {`);
|
||||||
ctx.addLine(` insert: n => n.elm.parentNode.replaceChild(frag${fragID}, n.elm),`);
|
ctx.addLine(` insert: n => n.elm.parentNode.replaceChild(frag${fragID}, n.elm),`);
|
||||||
@@ -1801,7 +1824,11 @@
|
|||||||
const variable = node.getAttribute("t-set");
|
const variable = node.getAttribute("t-set");
|
||||||
let value = node.getAttribute("t-value");
|
let value = node.getAttribute("t-value");
|
||||||
if (value) {
|
if (value) {
|
||||||
ctx.variables[variable] = value;
|
const varName = `_${ctx.generateID()}`;
|
||||||
|
const formattedValue = ctx.formatExpression(value);
|
||||||
|
ctx.addLine(`var ${varName} = ${formattedValue}`);
|
||||||
|
ctx.definedVariables[varName] = formattedValue;
|
||||||
|
ctx.variables[variable] = varName;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ctx.variables[variable] = node.childNodes;
|
ctx.variables[variable] = node.childNodes;
|
||||||
@@ -1862,12 +1889,32 @@
|
|||||||
nodeCopy.removeAttribute("t-call");
|
nodeCopy.removeAttribute("t-call");
|
||||||
// extract variables from nodecopy
|
// extract variables from nodecopy
|
||||||
const tempCtx = new Context();
|
const tempCtx = new Context();
|
||||||
|
tempCtx.nextID = ctx.rootContext.nextID;
|
||||||
qweb._compileNode(nodeCopy, tempCtx);
|
qweb._compileNode(nodeCopy, tempCtx);
|
||||||
const vars = Object.assign({}, ctx.variables, tempCtx.variables);
|
const vars = Object.assign({}, ctx.variables, tempCtx.variables);
|
||||||
|
var definedVariables = Object.assign({}, ctx.definedVariables, tempCtx.definedVariables);
|
||||||
|
ctx.rootContext.nextID = tempCtx.nextID;
|
||||||
|
// open new scope, if necessary
|
||||||
|
const hasNewVariables = Object.keys(definedVariables).length > 0;
|
||||||
|
if (hasNewVariables) {
|
||||||
|
ctx.addLine("{");
|
||||||
|
ctx.indent();
|
||||||
|
}
|
||||||
|
// add new variables, if any
|
||||||
|
for (let key in definedVariables) {
|
||||||
|
ctx.addLine(`let ${key} = ${definedVariables[key]}`);
|
||||||
|
}
|
||||||
|
// compile sub template
|
||||||
const subCtx = ctx
|
const subCtx = ctx
|
||||||
.subContext("caller", nodeCopy)
|
.subContext("caller", nodeCopy)
|
||||||
.subContext("variables", Object.create(vars));
|
.subContext("variables", Object.create(vars))
|
||||||
|
.subContext("definedVariables", Object.create(definedVariables));
|
||||||
qweb._compileNode(nodeTemplate, subCtx);
|
qweb._compileNode(nodeTemplate, subCtx);
|
||||||
|
// close new scope
|
||||||
|
if (hasNewVariables) {
|
||||||
|
ctx.dedent();
|
||||||
|
ctx.addLine("}");
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1941,7 +1988,7 @@
|
|||||||
ctx.addLine("//WIDGET");
|
ctx.addLine("//WIDGET");
|
||||||
ctx.rootContext.shouldDefineOwner = true;
|
ctx.rootContext.shouldDefineOwner = true;
|
||||||
let props = node.getAttribute("t-props");
|
let props = node.getAttribute("t-props");
|
||||||
let keepAlive = node.getAttribute("t-keep-alive") ? true : false;
|
let keepAlive = node.getAttribute("t-keepalive") ? true : false;
|
||||||
// t-on- events...
|
// t-on- events...
|
||||||
const events = [];
|
const events = [];
|
||||||
const attributes = node.attributes;
|
const attributes = node.attributes;
|
||||||
@@ -1981,17 +2028,17 @@
|
|||||||
: ctx.inLoop
|
: ctx.inLoop
|
||||||
? `String(-${widgetID} - i)`
|
? `String(-${widgetID} - i)`
|
||||||
: String(widgetID);
|
: String(widgetID);
|
||||||
ctx.addLine(`let w${widgetID} = ${templateID} in context.__widget__.cmap ? context.__widget__.children[context.__widget__.cmap[${templateID}]] : false;`);
|
ctx.addLine(`let w${widgetID} = ${templateID} in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[${templateID}]] : false;`);
|
||||||
ctx.addLine(`let props${widgetID} = ${props || "{}"};`);
|
ctx.addLine(`let props${widgetID} = ${props || "{}"};`);
|
||||||
ctx.addLine(`let isNew${widgetID} = !w${widgetID};`);
|
ctx.addLine(`let isNew${widgetID} = !w${widgetID};`);
|
||||||
// check if we can reuse current rendering promise
|
// check if we can reuse current rendering promise
|
||||||
ctx.addIf(`w${widgetID} && w${widgetID}.__widget__.renderPromise`);
|
ctx.addIf(`w${widgetID} && w${widgetID}.__owl__.renderPromise`);
|
||||||
ctx.addIf(`w${widgetID}.__widget__.isStarted`);
|
ctx.addIf(`w${widgetID}.__owl__.isStarted`);
|
||||||
ctx.addLine(`def${defID} = w${widgetID}.updateProps(props${widgetID}, extra.forceUpdate);`);
|
ctx.addLine(`def${defID} = w${widgetID}.updateProps(props${widgetID}, extra.forceUpdate);`);
|
||||||
ctx.addElse();
|
ctx.addElse();
|
||||||
ctx.addLine(`isNew${widgetID} = true`);
|
ctx.addLine(`isNew${widgetID} = true`);
|
||||||
ctx.addIf(`props${widgetID} === w${widgetID}.__widget__.renderProps`);
|
ctx.addIf(`props${widgetID} === w${widgetID}.__owl__.renderProps`);
|
||||||
ctx.addLine(`def${defID} = w${widgetID}.__widget__.renderPromise;`);
|
ctx.addLine(`def${defID} = w${widgetID}.__owl__.renderPromise;`);
|
||||||
ctx.addElse();
|
ctx.addElse();
|
||||||
ctx.addLine(`w${widgetID}.destroy();`);
|
ctx.addLine(`w${widgetID}.destroy();`);
|
||||||
ctx.addLine(`w${widgetID} = false`);
|
ctx.addLine(`w${widgetID} = false`);
|
||||||
@@ -2003,7 +2050,7 @@
|
|||||||
ctx.addLine(`def${defID} = w${widgetID}.updateProps(props${widgetID}, extra.forceUpdate);`);
|
ctx.addLine(`def${defID} = w${widgetID}.updateProps(props${widgetID}, extra.forceUpdate);`);
|
||||||
ctx.addElse();
|
ctx.addElse();
|
||||||
ctx.addLine(`w${widgetID} = new context.widgets['${value}'](owner, props${widgetID});`);
|
ctx.addLine(`w${widgetID} = new context.widgets['${value}'](owner, props${widgetID});`);
|
||||||
ctx.addLine(`context.__widget__.cmap[${templateID}] = w${widgetID}.__widget__.id;`);
|
ctx.addLine(`context.__owl__.cmap[${templateID}] = w${widgetID}.__owl__.id;`);
|
||||||
for (let [event, method] of events) {
|
for (let [event, method] of events) {
|
||||||
ctx.addLine(`w${widgetID}.on('${event}', owner, owner['${method}'])`);
|
ctx.addLine(`w${widgetID}.on('${event}', owner, owner['${method}'])`);
|
||||||
}
|
}
|
||||||
@@ -2015,9 +2062,9 @@
|
|||||||
ctx.closeIf();
|
ctx.closeIf();
|
||||||
ctx.closeIf();
|
ctx.closeIf();
|
||||||
ctx.addIf(`isNew${widgetID}`);
|
ctx.addIf(`isNew${widgetID}`);
|
||||||
ctx.addLine(`def${defID} = def${defID}.then(vnode=>{let pvnode=h(vnode.sel, {key: ${templateID}});c${ctx.parentNode}[_${dummyID}_index]=pvnode;pvnode.data.hook = {insert(vn){let nvn=w${widgetID}._mount(vnode, vn.elm);pvnode.elm=nvn.elm},remove(){w${widgetID}.${keepAlive ? "unmount" : "destroy"}()},destroy(){w${widgetID}.${keepAlive ? "unmount" : "destroy"}()}}; w${widgetID}.__widget__.pvnode = pvnode;});`);
|
ctx.addLine(`def${defID} = def${defID}.then(vnode=>{let pvnode=h(vnode.sel, {key: ${templateID}});c${ctx.parentNode}[_${dummyID}_index]=pvnode;pvnode.data.hook = {insert(vn){let nvn=w${widgetID}._mount(vnode, vn.elm);pvnode.elm=nvn.elm},remove(){w${widgetID}.${keepAlive ? "unmount" : "destroy"}()},destroy(){w${widgetID}.${keepAlive ? "unmount" : "destroy"}()}}; w${widgetID}.__owl__.pvnode = pvnode;});`);
|
||||||
ctx.addElse();
|
ctx.addElse();
|
||||||
ctx.addLine(`def${defID} = def${defID}.then(()=>{if (w${widgetID}.__widget__.isDestroyed) {return};let vnode;if (!w${widgetID}.__widget__.vnode){vnode=w${widgetID}.__widget__.pvnode} else { vnode=h(w${widgetID}.__widget__.vnode.sel, {key: ${templateID}});vnode.elm=w${widgetID}.el;vnode.data.hook = {insert(a){a.elm.parentNode.replaceChild(w${widgetID}.el,a.elm);a.elm=w${widgetID}.el;w${widgetID}.__mount();},remove(){w${widgetID}.${keepAlive ? "unmount" : "destroy"}()}, destroy() {w${widgetID}.${keepAlive ? "unmount" : "destroy"}()}}}c${ctx.parentNode}[_${dummyID}_index]=vnode;});`);
|
ctx.addLine(`def${defID} = def${defID}.then(()=>{if (w${widgetID}.__owl__.isDestroyed) {return};let vnode;if (!w${widgetID}.__owl__.vnode){vnode=w${widgetID}.__owl__.pvnode} else { vnode=h(w${widgetID}.__owl__.vnode.sel, {key: ${templateID}});vnode.elm=w${widgetID}.el;vnode.data.hook = {insert(a){a.elm.parentNode.replaceChild(w${widgetID}.el,a.elm);a.elm=w${widgetID}.el;w${widgetID}.__mount();},remove(){w${widgetID}.${keepAlive ? "unmount" : "destroy"}()}, destroy() {w${widgetID}.${keepAlive ? "unmount" : "destroy"}()}}}c${ctx.parentNode}[_${dummyID}_index]=vnode;});`);
|
||||||
ctx.closeIf();
|
ctx.closeIf();
|
||||||
ctx.addLine(`extra.promises.push(def${defID});`);
|
ctx.addLine(`extra.promises.push(def${defID});`);
|
||||||
if (node.getAttribute("t-if") || node.getAttribute("t-else")) {
|
if (node.getAttribute("t-if") || node.getAttribute("t-else")) {
|
||||||
@@ -2059,6 +2106,7 @@
|
|||||||
class Store extends EventBus {
|
class Store extends EventBus {
|
||||||
constructor(config, options = {}) {
|
constructor(config, options = {}) {
|
||||||
super();
|
super();
|
||||||
|
this._commitLevel = 0;
|
||||||
this._isMutating = false;
|
this._isMutating = false;
|
||||||
this.history = [];
|
this.history = [];
|
||||||
this.debug = options.debug || false;
|
this.debug = options.debug || false;
|
||||||
@@ -2090,42 +2138,52 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async commit(type, payload) {
|
commit(type, payload) {
|
||||||
if (!this.mutations[type]) {
|
if (!this.mutations[type]) {
|
||||||
throw new Error(`[Error] mutation ${type} is undefined`);
|
throw new Error(`[Error] mutation ${type} is undefined`);
|
||||||
}
|
}
|
||||||
const currentRev = this.observer.__rev__;
|
this._commitLevel++;
|
||||||
|
const currentRev = this.observer.rev;
|
||||||
this._isMutating = true;
|
this._isMutating = true;
|
||||||
this.observer.allowMutations = true;
|
this.observer.allowMutations = true;
|
||||||
this.mutations[type].call(null, { state: this.state, set: this.observer.set }, payload);
|
const res = this.mutations[type].call(null, {
|
||||||
this.observer.allowMutations = false;
|
commit: this.commit.bind(this),
|
||||||
if (this.debug) {
|
state: this.state,
|
||||||
this.history.push({
|
set: this.observer.set
|
||||||
state: this.state,
|
}, payload);
|
||||||
mutation: type,
|
if (this._commitLevel === 1) {
|
||||||
payload: payload
|
this.observer.allowMutations = false;
|
||||||
|
if (this.debug) {
|
||||||
|
this.history.push({
|
||||||
|
state: this.state,
|
||||||
|
mutation: type,
|
||||||
|
payload: payload
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Promise.resolve().then(() => {
|
||||||
|
if (this._isMutating) {
|
||||||
|
this._isMutating = false;
|
||||||
|
if (currentRev !== this.observer.rev) {
|
||||||
|
this.trigger("update", this.state);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
await Promise.resolve();
|
this._commitLevel--;
|
||||||
if (this._isMutating) {
|
return res;
|
||||||
this._isMutating = false;
|
|
||||||
if (currentRev !== this.observer.__rev__) {
|
|
||||||
this.trigger("update", this.state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function makeObserver() {
|
function makeObserver() {
|
||||||
const observer = {
|
const observer = {
|
||||||
__rev__: 0,
|
rev: 1,
|
||||||
allowMutations: true,
|
allowMutations: true,
|
||||||
observe: observe,
|
observe: observe,
|
||||||
set: set
|
set: set
|
||||||
};
|
};
|
||||||
function set(target, key, value) {
|
function set(target, key, value) {
|
||||||
addProp(target, key, value);
|
addProp(target, key, value);
|
||||||
target.__rev__++;
|
target.__owl__.rev++;
|
||||||
observer.__rev__++;
|
observer.rev++;
|
||||||
}
|
}
|
||||||
function addProp(obj, key, value) {
|
function addProp(obj, key, value) {
|
||||||
Object.defineProperty(obj, key, {
|
Object.defineProperty(obj, key, {
|
||||||
@@ -2138,19 +2196,24 @@
|
|||||||
throw new Error(`State cannot be changed outside a mutation! (key: "${key}", val: "${newVal}")`);
|
throw new Error(`State cannot be changed outside a mutation! (key: "${key}", val: "${newVal}")`);
|
||||||
}
|
}
|
||||||
if (newVal !== value) {
|
if (newVal !== value) {
|
||||||
|
unobserve(value);
|
||||||
value = newVal;
|
value = newVal;
|
||||||
observe(newVal);
|
observe(newVal, obj);
|
||||||
obj.__rev__++;
|
obj.__owl__.rev++;
|
||||||
observer.__rev__++;
|
observer.rev++;
|
||||||
|
let parent = obj;
|
||||||
|
do {
|
||||||
|
parent.__owl__.deepRev++;
|
||||||
|
} while ((parent = parent.__owl__.parent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
observe(value);
|
observe(value, obj);
|
||||||
}
|
}
|
||||||
function observeObj(obj) {
|
function observeObj(obj, parent) {
|
||||||
const keys = Object.keys(obj);
|
const keys = Object.keys(obj);
|
||||||
obj.__rev__ = 0;
|
obj.__owl__ = { rev: 1, deepRev: 1, parent };
|
||||||
Object.defineProperty(obj, "__rev__", { enumerable: false });
|
Object.defineProperty(obj, "__owl__", { enumerable: false });
|
||||||
for (let key of keys) {
|
for (let key of keys) {
|
||||||
addProp(obj, key, obj[key]);
|
addProp(obj, key, obj[key]);
|
||||||
}
|
}
|
||||||
@@ -2169,8 +2232,12 @@
|
|||||||
for (let method of methodsToPatch) {
|
for (let method of methodsToPatch) {
|
||||||
const initialMethod = ArrayProto[method];
|
const initialMethod = ArrayProto[method];
|
||||||
ModifiedArrayProto[method] = function (...args) {
|
ModifiedArrayProto[method] = function (...args) {
|
||||||
observer.__rev__++;
|
observer.rev++;
|
||||||
this.__rev__++;
|
this.__owl__.rev++;
|
||||||
|
let parent = this;
|
||||||
|
do {
|
||||||
|
parent.__owl__.deepRev++;
|
||||||
|
} while ((parent = parent.__owl__.parent));
|
||||||
let inserted;
|
let inserted;
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case "push":
|
case "push":
|
||||||
@@ -2183,33 +2250,42 @@
|
|||||||
}
|
}
|
||||||
if (inserted) {
|
if (inserted) {
|
||||||
for (let elem of inserted) {
|
for (let elem of inserted) {
|
||||||
observe(elem);
|
observe(elem, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return initialMethod.call(this, ...args);
|
return initialMethod.call(this, ...args);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function observeArr(arr) {
|
function observeArr(arr, parent) {
|
||||||
arr.__rev__ = 0;
|
arr.__owl__ = { rev: 1, deepRev: 1, parent };
|
||||||
Object.defineProperty(arr, "__rev__", { enumerable: false });
|
Object.defineProperty(arr, "__owl__", { enumerable: false });
|
||||||
arr.__proto__ = ModifiedArrayProto;
|
arr.__proto__ = ModifiedArrayProto;
|
||||||
for (let i = 0; i < arr.length; i++) {
|
for (let i = 0; i < arr.length; i++) {
|
||||||
observe(arr[i]);
|
observe(arr[i], arr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function observe(value) {
|
function observe(value, parent) {
|
||||||
|
if (value === null) {
|
||||||
|
// fun fact: typeof null === 'object'
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (typeof value !== "object") {
|
if (typeof value !== "object") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ("__rev__" in value) {
|
if ("__owl__" in value) {
|
||||||
// already observed
|
// already observed
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
observeArr(value);
|
observeArr(value, parent);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
observeObj(value);
|
observeObj(value, parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function unobserve(target) {
|
||||||
|
if (target !== null && typeof target === "object") {
|
||||||
|
delete target.__owl__;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return observer;
|
return observer;
|
||||||
@@ -2217,15 +2293,44 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Connect function
|
// Connect function
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
function setStoreProps(__widget__, storeProps) {
|
function revNumber(o) {
|
||||||
__widget__.currentStoreProps = storeProps;
|
if (o !== null && typeof o === "object" && o.__owl__) {
|
||||||
__widget__.currentStoreRevs = {};
|
return o.__owl__.rev;
|
||||||
__widget__.currentStoreRev = storeProps.__rev__;
|
|
||||||
for (let key in storeProps) {
|
|
||||||
__widget__.currentStoreRevs[key] = storeProps[key].__rev__;
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
function connect(mapStateToProps) {
|
function deepRevNumber(o) {
|
||||||
|
if (o !== null && typeof o === "object" && o.__owl__) {
|
||||||
|
return o.__owl__.deepRev;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
function connect(mapStateToProps, options = {}) {
|
||||||
|
let hashFunction = options.hashFunction || null;
|
||||||
|
if (!hashFunction) {
|
||||||
|
let deep = "deep" in options ? options.deep : true;
|
||||||
|
let defaultRevFunction = deep ? deepRevNumber : revNumber;
|
||||||
|
hashFunction = function ({ storeProps }, options) {
|
||||||
|
const { currentStoreProps } = options;
|
||||||
|
if ("__owl__" in storeProps) {
|
||||||
|
return defaultRevFunction(storeProps);
|
||||||
|
}
|
||||||
|
let hash = 0;
|
||||||
|
for (let key in storeProps) {
|
||||||
|
const val = storeProps[key];
|
||||||
|
const hashVal = defaultRevFunction(val);
|
||||||
|
if (hashVal === 0) {
|
||||||
|
if (val !== currentStoreProps[key]) {
|
||||||
|
options.didChange = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hash += hashVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
};
|
||||||
|
}
|
||||||
return function (Comp) {
|
return function (Comp) {
|
||||||
return class extends Comp {
|
return class extends Comp {
|
||||||
constructor(parent, props) {
|
constructor(parent, props) {
|
||||||
@@ -2234,30 +2339,37 @@
|
|||||||
const storeProps = mapStateToProps(env.store.state, ownProps);
|
const storeProps = mapStateToProps(env.store.state, ownProps);
|
||||||
const mergedProps = Object.assign({}, props || {}, storeProps);
|
const mergedProps = Object.assign({}, props || {}, storeProps);
|
||||||
super(parent, mergedProps);
|
super(parent, mergedProps);
|
||||||
setStoreProps(this.__widget__, storeProps);
|
this.__owl__.ownProps = ownProps;
|
||||||
this.__widget__.ownProps = ownProps;
|
this.__owl__.currentStoreProps = storeProps;
|
||||||
|
this.__owl__.storeHash = hashFunction({
|
||||||
|
state: env.store.state,
|
||||||
|
storeProps: storeProps,
|
||||||
|
revNumber,
|
||||||
|
deepRevNumber
|
||||||
|
}, {
|
||||||
|
currentStoreProps: storeProps
|
||||||
|
});
|
||||||
}
|
}
|
||||||
mounted() {
|
mounted() {
|
||||||
this.env.store.on("update", this, () => {
|
this.env.store.on("update", this, () => {
|
||||||
const ownProps = this.__widget__.ownProps;
|
const ownProps = this.__owl__.ownProps;
|
||||||
const storeProps = mapStateToProps(this.env.store.state, ownProps);
|
const storeProps = mapStateToProps(this.env.store.state, ownProps);
|
||||||
let didChange = false;
|
const options = {
|
||||||
if (this.__widget__.currentStoreRev !== storeProps.__rev__) {
|
currentStoreProps: this.__owl__.currentStoreProps
|
||||||
setStoreProps(this.__widget__, storeProps);
|
};
|
||||||
|
const storeHash = hashFunction({
|
||||||
|
state: this.env.store.state,
|
||||||
|
storeProps: storeProps,
|
||||||
|
revNumber,
|
||||||
|
deepRevNumber
|
||||||
|
}, options);
|
||||||
|
let didChange = options.didChange;
|
||||||
|
if (storeHash !== this.__owl__.storeHash) {
|
||||||
didChange = true;
|
didChange = true;
|
||||||
}
|
this.__owl__.storeHash = storeHash;
|
||||||
else {
|
|
||||||
const revs = this.__widget__.currentStoreRevs;
|
|
||||||
for (let key in storeProps) {
|
|
||||||
const val = storeProps[key];
|
|
||||||
if (val.__rev__ !== revs[key]) {
|
|
||||||
didChange = true;
|
|
||||||
revs[key] = val.__rev__;
|
|
||||||
this.__widget__.currentStoreProps[key] = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (didChange) {
|
if (didChange) {
|
||||||
|
this.__owl__.currentStoreProps = storeProps;
|
||||||
this.updateProps(ownProps, false);
|
this.updateProps(ownProps, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -2268,11 +2380,11 @@
|
|||||||
super.willUnmount();
|
super.willUnmount();
|
||||||
}
|
}
|
||||||
updateProps(nextProps, forceUpdate) {
|
updateProps(nextProps, forceUpdate) {
|
||||||
if (this.__widget__.ownProps !== nextProps) {
|
if (this.__owl__.ownProps !== nextProps) {
|
||||||
this.__widget__.currentStoreProps = mapStateToProps(this.env.store.state, nextProps);
|
this.__owl__.currentStoreProps = mapStateToProps(this.env.store.state, nextProps);
|
||||||
}
|
}
|
||||||
this.__widget__.ownProps = nextProps;
|
this.__owl__.ownProps = nextProps;
|
||||||
const mergedProps = Object.assign({}, nextProps, this.__widget__.currentStoreProps);
|
const mergedProps = Object.assign({}, nextProps, this.__owl__.currentStoreProps);
|
||||||
return super.updateProps(mergedProps, forceUpdate);
|
return super.updateProps(mergedProps, forceUpdate);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -2296,7 +2408,7 @@
|
|||||||
exports.extras = extras;
|
exports.extras = extras;
|
||||||
|
|
||||||
exports._version = '0.6.0';
|
exports._version = '0.6.0';
|
||||||
exports._date = '2019-04-12T13:25:16.523Z';
|
exports._date = '2019-04-16T08:20:25.817Z';
|
||||||
exports._hash = 'd328360';
|
exports._hash = '9dd8a36';
|
||||||
|
|
||||||
}(this.owl = this.owl || {}));
|
}(this.owl = this.owl || {}));
|
||||||
|
|||||||
Reference in New Issue
Block a user