mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[IMP] update owl to v2.0.0-beta.3
This commit is contained in:
@@ -266,10 +266,14 @@
|
|||||||
this[eventKey] = data;
|
this[eventKey] = data;
|
||||||
this.addEventListener(evName, listener, { capture });
|
this.addEventListener(evName, listener, { capture });
|
||||||
}
|
}
|
||||||
|
function remove() {
|
||||||
|
delete this[eventKey];
|
||||||
|
this.removeEventListener(evName, listener, { capture });
|
||||||
|
}
|
||||||
function update(data) {
|
function update(data) {
|
||||||
this[eventKey] = data;
|
this[eventKey] = data;
|
||||||
}
|
}
|
||||||
return { setup, update };
|
return { setup, update, remove };
|
||||||
}
|
}
|
||||||
// Synthetic handler: a form of event delegation that allows placing only one
|
// Synthetic handler: a form of event delegation that allows placing only one
|
||||||
// listener per event type.
|
// listener per event type.
|
||||||
@@ -286,7 +290,10 @@
|
|||||||
_data[currentId] = data;
|
_data[currentId] = data;
|
||||||
this[eventKey] = _data;
|
this[eventKey] = _data;
|
||||||
}
|
}
|
||||||
return { setup, update: setup };
|
function remove() {
|
||||||
|
delete this[eventKey];
|
||||||
|
}
|
||||||
|
return { setup, update: setup, remove };
|
||||||
}
|
}
|
||||||
function nativeToSyntheticEvent(eventKey, event) {
|
function nativeToSyntheticEvent(eventKey, event) {
|
||||||
let dom = event.target;
|
let dom = event.target;
|
||||||
@@ -1281,6 +1288,75 @@
|
|||||||
return new VHtml(str);
|
return new VHtml(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createCatcher(eventsSpec) {
|
||||||
|
let setupFns = [];
|
||||||
|
let removeFns = [];
|
||||||
|
for (let name in eventsSpec) {
|
||||||
|
let index = eventsSpec[name];
|
||||||
|
let { setup, remove } = createEventHandler(name);
|
||||||
|
setupFns[index] = setup;
|
||||||
|
removeFns[index] = remove;
|
||||||
|
}
|
||||||
|
let n = setupFns.length;
|
||||||
|
class VCatcher {
|
||||||
|
constructor(child, handlers) {
|
||||||
|
this.afterNode = null;
|
||||||
|
this.child = child;
|
||||||
|
this.handlers = handlers;
|
||||||
|
}
|
||||||
|
mount(parent, afterNode) {
|
||||||
|
this.parentEl = parent;
|
||||||
|
this.afterNode = afterNode;
|
||||||
|
this.child.mount(parent, afterNode);
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
let origFn = this.handlers[i][0];
|
||||||
|
const self = this;
|
||||||
|
this.handlers[i][0] = function (ev) {
|
||||||
|
const target = ev.target;
|
||||||
|
let currentNode = self.child.firstNode();
|
||||||
|
const afterNode = self.afterNode;
|
||||||
|
while (currentNode !== afterNode) {
|
||||||
|
if (currentNode.contains(target)) {
|
||||||
|
return origFn.call(this, ev);
|
||||||
|
}
|
||||||
|
currentNode = currentNode.nextSibling;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
setupFns[i].call(parent, this.handlers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
moveBefore(other, afterNode) {
|
||||||
|
this.afterNode = null;
|
||||||
|
this.child.moveBefore(other ? other.child : null, afterNode);
|
||||||
|
}
|
||||||
|
patch(other, withBeforeRemove) {
|
||||||
|
if (this === other) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.handlers = other.handlers;
|
||||||
|
this.child.patch(other.child, withBeforeRemove);
|
||||||
|
}
|
||||||
|
beforeRemove() {
|
||||||
|
this.child.beforeRemove();
|
||||||
|
}
|
||||||
|
remove() {
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
removeFns[i].call(this.parentEl);
|
||||||
|
}
|
||||||
|
this.child.remove();
|
||||||
|
}
|
||||||
|
firstNode() {
|
||||||
|
return this.child.firstNode();
|
||||||
|
}
|
||||||
|
toString() {
|
||||||
|
return this.child.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return function (child, handlers) {
|
||||||
|
return new VCatcher(child, handlers);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function mount$1(vnode, fixture, afterNode = null) {
|
function mount$1(vnode, fixture, afterNode = null) {
|
||||||
vnode.mount(fixture, afterNode);
|
vnode.mount(fixture, afterNode);
|
||||||
}
|
}
|
||||||
@@ -2733,24 +2809,31 @@
|
|||||||
function tokenize(expr) {
|
function tokenize(expr) {
|
||||||
const result = [];
|
const result = [];
|
||||||
let token = true;
|
let token = true;
|
||||||
while (token) {
|
let error;
|
||||||
expr = expr.trim();
|
let current = expr;
|
||||||
if (expr) {
|
try {
|
||||||
for (let tokenizer of TOKENIZERS) {
|
while (token) {
|
||||||
token = tokenizer(expr);
|
current = current.trim();
|
||||||
if (token) {
|
if (current) {
|
||||||
result.push(token);
|
for (let tokenizer of TOKENIZERS) {
|
||||||
expr = expr.slice(token.size || token.value.length);
|
token = tokenizer(current);
|
||||||
break;
|
if (token) {
|
||||||
|
result.push(token);
|
||||||
|
current = current.slice(token.size || token.value.length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
else {
|
token = false;
|
||||||
token = false;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (expr.length) {
|
catch (e) {
|
||||||
throw new Error(`Tokenizer error: could not tokenize "${expr}"`);
|
error = e; // Silence all errors and throw a generic error below
|
||||||
|
}
|
||||||
|
if (current.length || error) {
|
||||||
|
throw new Error(`Tokenizer error: could not tokenize \`${expr}\``);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -2955,7 +3038,7 @@
|
|||||||
}, params);
|
}, params);
|
||||||
}
|
}
|
||||||
class CodeTarget {
|
class CodeTarget {
|
||||||
constructor(name) {
|
constructor(name, on) {
|
||||||
this.indentLevel = 0;
|
this.indentLevel = 0;
|
||||||
this.loopLevel = 0;
|
this.loopLevel = 0;
|
||||||
this.code = [];
|
this.code = [];
|
||||||
@@ -2966,6 +3049,7 @@
|
|||||||
this.refInfo = {};
|
this.refInfo = {};
|
||||||
this.shouldProtectScope = false;
|
this.shouldProtectScope = false;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.on = on || null;
|
||||||
}
|
}
|
||||||
addLine(line, idx) {
|
addLine(line, idx) {
|
||||||
const prefix = new Array(this.indentLevel + 2).join(" ");
|
const prefix = new Array(this.indentLevel + 2).join(" ");
|
||||||
@@ -3015,7 +3099,7 @@
|
|||||||
this.targets = [];
|
this.targets = [];
|
||||||
this.target = new CodeTarget("template");
|
this.target = new CodeTarget("template");
|
||||||
this.translatableAttributes = TRANSLATABLE_ATTRS;
|
this.translatableAttributes = TRANSLATABLE_ATTRS;
|
||||||
this.staticCalls = [];
|
this.staticDefs = [];
|
||||||
this.helpers = new Set();
|
this.helpers = new Set();
|
||||||
this.translateFn = options.translateFn || ((s) => s);
|
this.translateFn = options.translateFn || ((s) => s);
|
||||||
if (options.translatableAttributes) {
|
if (options.translatableAttributes) {
|
||||||
@@ -3058,8 +3142,8 @@
|
|||||||
if (this.templateName) {
|
if (this.templateName) {
|
||||||
mainCode.push(`// Template name: "${this.templateName}"`);
|
mainCode.push(`// Template name: "${this.templateName}"`);
|
||||||
}
|
}
|
||||||
for (let { id, template } of this.staticCalls) {
|
for (let { id, expr } of this.staticDefs) {
|
||||||
mainCode.push(`const ${id} = getTemplate(${template});`);
|
mainCode.push(`const ${id} = ${expr};`);
|
||||||
}
|
}
|
||||||
// define all blocks
|
// define all blocks
|
||||||
if (this.blocks.length) {
|
if (this.blocks.length) {
|
||||||
@@ -3095,19 +3179,21 @@
|
|||||||
}
|
}
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
compileInNewTarget(prefix, ast, ctx) {
|
compileInNewTarget(prefix, ast, ctx, on) {
|
||||||
const name = this.generateId(prefix);
|
const name = this.generateId(prefix);
|
||||||
const initialTarget = this.target;
|
const initialTarget = this.target;
|
||||||
const target = new CodeTarget(name);
|
const target = new CodeTarget(name, on);
|
||||||
this.targets.push(target);
|
this.targets.push(target);
|
||||||
this.target = target;
|
this.target = target;
|
||||||
const subCtx = createContext(ctx);
|
this.compileAST(ast, createContext(ctx));
|
||||||
this.compileAST(ast, subCtx);
|
|
||||||
this.target = initialTarget;
|
this.target = initialTarget;
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
addLine(line) {
|
addLine(line, idx) {
|
||||||
this.target.addLine(line);
|
this.target.addLine(line, idx);
|
||||||
|
}
|
||||||
|
define(varName, expr) {
|
||||||
|
this.addLine(`const ${varName} = ${expr};`);
|
||||||
}
|
}
|
||||||
generateId(prefix = "") {
|
generateId(prefix = "") {
|
||||||
this.ids[prefix] = (this.ids[prefix] || 0) + 1;
|
this.ids[prefix] = (this.ids[prefix] || 0) + 1;
|
||||||
@@ -3149,10 +3235,13 @@
|
|||||||
blockExpr = `toggler(${tKeyExpr}, ${blockExpr})`;
|
blockExpr = `toggler(${tKeyExpr}, ${blockExpr})`;
|
||||||
}
|
}
|
||||||
if (block.isRoot && !ctx.preventRoot) {
|
if (block.isRoot && !ctx.preventRoot) {
|
||||||
|
if (this.target.on) {
|
||||||
|
blockExpr = this.wrapWithEventCatcher(blockExpr, this.target.on);
|
||||||
|
}
|
||||||
this.addLine(`return ${blockExpr};`);
|
this.addLine(`return ${blockExpr};`);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.addLine(`let ${block.varName} = ${blockExpr};`);
|
this.define(block.varName, blockExpr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -3180,7 +3269,7 @@
|
|||||||
if (!mapping.has(tok.varName)) {
|
if (!mapping.has(tok.varName)) {
|
||||||
const varId = this.generateId("v");
|
const varId = this.generateId("v");
|
||||||
mapping.set(tok.varName, varId);
|
mapping.set(tok.varName, varId);
|
||||||
this.addLine(`const ${varId} = ${tok.value};`);
|
this.define(varId, tok.value);
|
||||||
}
|
}
|
||||||
tok.value = mapping.get(tok.varName);
|
tok.value = mapping.get(tok.varName);
|
||||||
}
|
}
|
||||||
@@ -3319,7 +3408,7 @@
|
|||||||
this.blocks.push(block);
|
this.blocks.push(block);
|
||||||
if (ast.dynamicTag) {
|
if (ast.dynamicTag) {
|
||||||
const tagExpr = this.generateId("tag");
|
const tagExpr = this.generateId("tag");
|
||||||
this.addLine(`let ${tagExpr} = ${compileExpr(ast.dynamicTag)};`);
|
this.define(tagExpr, compileExpr(ast.dynamicTag));
|
||||||
block.dynamicTagName = tagExpr;
|
block.dynamicTagName = tagExpr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3401,10 +3490,10 @@
|
|||||||
const { hasDynamicChildren, baseExpr, expr, eventType, shouldNumberize, shouldTrim, targetAttr, specialInitTargetAttr, } = ast.model;
|
const { hasDynamicChildren, baseExpr, expr, eventType, shouldNumberize, shouldTrim, targetAttr, specialInitTargetAttr, } = ast.model;
|
||||||
const baseExpression = compileExpr(baseExpr);
|
const baseExpression = compileExpr(baseExpr);
|
||||||
const bExprId = this.generateId("bExpr");
|
const bExprId = this.generateId("bExpr");
|
||||||
this.addLine(`const ${bExprId} = ${baseExpression};`);
|
this.define(bExprId, baseExpression);
|
||||||
const expression = compileExpr(expr);
|
const expression = compileExpr(expr);
|
||||||
const exprId = this.generateId("expr");
|
const exprId = this.generateId("expr");
|
||||||
this.addLine(`const ${exprId} = ${expression};`);
|
this.define(exprId, expression);
|
||||||
const fullExpression = `${bExprId}[${exprId}]`;
|
const fullExpression = `${bExprId}[${exprId}]`;
|
||||||
let idx;
|
let idx;
|
||||||
if (specialInitTargetAttr) {
|
if (specialInitTargetAttr) {
|
||||||
@@ -3414,7 +3503,7 @@
|
|||||||
else if (hasDynamicChildren) {
|
else if (hasDynamicChildren) {
|
||||||
const bValueId = this.generateId("bValue");
|
const bValueId = this.generateId("bValue");
|
||||||
tModelSelectedExpr = `${bValueId}`;
|
tModelSelectedExpr = `${bValueId}`;
|
||||||
this.addLine(`let ${tModelSelectedExpr} = ${fullExpression}`);
|
this.define(tModelSelectedExpr, fullExpression);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
idx = block.insertData(`${fullExpression}`, "attr");
|
idx = block.insertData(`${fullExpression}`, "attr");
|
||||||
@@ -3462,14 +3551,14 @@
|
|||||||
const children = block.children.slice();
|
const children = block.children.slice();
|
||||||
let current = children.shift();
|
let current = children.shift();
|
||||||
for (let i = codeIdx; i < code.length; i++) {
|
for (let i = codeIdx; i < code.length; i++) {
|
||||||
if (code[i].trimStart().startsWith(`let ${current.varName} `)) {
|
if (code[i].trimStart().startsWith(`const ${current.varName} `)) {
|
||||||
code[i] = code[i].replace(`let ${current.varName}`, current.varName);
|
code[i] = code[i].replace(`const ${current.varName}`, current.varName);
|
||||||
current = children.shift();
|
current = children.shift();
|
||||||
if (!current)
|
if (!current)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.target.addLine(`let ${block.children.map((c) => c.varName)};`, codeIdx);
|
this.addLine(`let ${block.children.map((c) => c.varName)};`, codeIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3557,14 +3646,14 @@
|
|||||||
const children = block.children.slice();
|
const children = block.children.slice();
|
||||||
let current = children.shift();
|
let current = children.shift();
|
||||||
for (let i = codeIdx; i < code.length; i++) {
|
for (let i = codeIdx; i < code.length; i++) {
|
||||||
if (code[i].trimStart().startsWith(`let ${current.varName} `)) {
|
if (code[i].trimStart().startsWith(`const ${current.varName} `)) {
|
||||||
code[i] = code[i].replace(`let ${current.varName}`, current.varName);
|
code[i] = code[i].replace(`const ${current.varName}`, current.varName);
|
||||||
current = children.shift();
|
current = children.shift();
|
||||||
if (!current)
|
if (!current)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.target.addLine(`let ${block.children.map((c) => c.varName)};`, codeIdx);
|
this.addLine(`let ${block.children.map((c) => c.varName)};`, codeIdx);
|
||||||
}
|
}
|
||||||
// note: this part is duplicated from end of compilemulti:
|
// note: this part is duplicated from end of compilemulti:
|
||||||
const args = block.children.map((c) => c.varName).join(", ");
|
const args = block.children.map((c) => c.varName).join(", ");
|
||||||
@@ -3585,10 +3674,10 @@
|
|||||||
const l = `l_block${block.id}`;
|
const l = `l_block${block.id}`;
|
||||||
const c = `c_block${block.id}`;
|
const c = `c_block${block.id}`;
|
||||||
this.helpers.add("prepareList");
|
this.helpers.add("prepareList");
|
||||||
this.addLine(`const [${keys}, ${vals}, ${l}, ${c}] = prepareList(${compileExpr(ast.collection)});`);
|
this.define(`[${keys}, ${vals}, ${l}, ${c}]`, `prepareList(${compileExpr(ast.collection)});`);
|
||||||
// Throw errors on duplicate keys in dev mode
|
// Throw errors on duplicate keys in dev mode
|
||||||
if (this.dev) {
|
if (this.dev) {
|
||||||
this.addLine(`const keys${block.id} = new Set();`);
|
this.define(`keys${block.id}`, `new Set()`);
|
||||||
}
|
}
|
||||||
this.addLine(`for (let ${loopVar} = 0; ${loopVar} < ${l}; ${loopVar}++) {`);
|
this.addLine(`for (let ${loopVar} = 0; ${loopVar} < ${l}; ${loopVar}++) {`);
|
||||||
this.target.indentLevel++;
|
this.target.indentLevel++;
|
||||||
@@ -3605,7 +3694,7 @@
|
|||||||
if (!ast.hasNoValue) {
|
if (!ast.hasNoValue) {
|
||||||
this.addLine(`ctx[\`${ast.elem}_value\`] = ${keys}[${loopVar}];`);
|
this.addLine(`ctx[\`${ast.elem}_value\`] = ${keys}[${loopVar}];`);
|
||||||
}
|
}
|
||||||
this.addLine(`let key${this.target.loopLevel} = ${ast.key ? compileExpr(ast.key) : loopVar};`);
|
this.define(`key${this.target.loopLevel}`, ast.key ? compileExpr(ast.key) : loopVar);
|
||||||
if (this.dev) {
|
if (this.dev) {
|
||||||
// Throw error on duplicate keys in dev mode
|
// Throw error on duplicate keys in dev mode
|
||||||
this.addLine(`if (keys${block.id}.has(key${this.target.loopLevel})) { throw new Error(\`Got duplicate key in t-foreach: \${key${this.target.loopLevel}}\`)}`);
|
this.addLine(`if (keys${block.id}.has(key${this.target.loopLevel})) { throw new Error(\`Got duplicate key in t-foreach: \${key${this.target.loopLevel}}\`)}`);
|
||||||
@@ -3615,8 +3704,8 @@
|
|||||||
if (ast.memo) {
|
if (ast.memo) {
|
||||||
this.target.hasCache = true;
|
this.target.hasCache = true;
|
||||||
id = this.generateId();
|
id = this.generateId();
|
||||||
this.addLine(`let memo${id} = ${compileExpr(ast.memo)}`);
|
this.define(`memo${id}`, compileExpr(ast.memo));
|
||||||
this.addLine(`let vnode${id} = cache[key${this.target.loopLevel}];`);
|
this.define(`vnode${id}`, `cache[key${this.target.loopLevel}];`);
|
||||||
this.addLine(`if (vnode${id}) {`);
|
this.addLine(`if (vnode${id}) {`);
|
||||||
this.target.indentLevel++;
|
this.target.indentLevel++;
|
||||||
this.addLine(`if (shallowEqual(vnode${id}.memo, memo${id})) {`);
|
this.addLine(`if (shallowEqual(vnode${id}.memo, memo${id})) {`);
|
||||||
@@ -3644,7 +3733,7 @@
|
|||||||
}
|
}
|
||||||
compileTKey(ast, ctx) {
|
compileTKey(ast, ctx) {
|
||||||
const tKeyExpr = this.generateId("tKey_");
|
const tKeyExpr = this.generateId("tKey_");
|
||||||
this.addLine(`const ${tKeyExpr} = ${compileExpr(ast.expr)};`);
|
this.define(tKeyExpr, compileExpr(ast.expr));
|
||||||
ctx = createContext(ctx, {
|
ctx = createContext(ctx, {
|
||||||
tKeyExpr,
|
tKeyExpr,
|
||||||
block: ctx.block,
|
block: ctx.block,
|
||||||
@@ -3689,14 +3778,14 @@
|
|||||||
const children = block.children.slice();
|
const children = block.children.slice();
|
||||||
let current = children.shift();
|
let current = children.shift();
|
||||||
for (let i = codeIdx; i < code.length; i++) {
|
for (let i = codeIdx; i < code.length; i++) {
|
||||||
if (code[i].trimStart().startsWith(`let ${current.varName} `)) {
|
if (code[i].trimStart().startsWith(`const ${current.varName} `)) {
|
||||||
code[i] = code[i].replace(`let ${current.varName}`, current.varName);
|
code[i] = code[i].replace(`const ${current.varName}`, current.varName);
|
||||||
current = children.shift();
|
current = children.shift();
|
||||||
if (!current)
|
if (!current)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.target.addLine(`let ${block.children.map((c) => c.varName)};`, codeIdx);
|
this.addLine(`let ${block.children.map((c) => c.varName)};`, codeIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const args = block.children.map((c) => c.varName).join(", ");
|
const args = block.children.map((c) => c.varName).join(", ");
|
||||||
@@ -3727,7 +3816,7 @@
|
|||||||
const key = `key + \`${this.generateComponentKey()}\``;
|
const key = `key + \`${this.generateComponentKey()}\``;
|
||||||
if (isDynamic) {
|
if (isDynamic) {
|
||||||
const templateVar = this.generateId("template");
|
const templateVar = this.generateId("template");
|
||||||
this.addLine(`const ${templateVar} = ${subTemplate};`);
|
this.define(templateVar, subTemplate);
|
||||||
block = this.createBlock(block, "multi", ctx);
|
block = this.createBlock(block, "multi", ctx);
|
||||||
this.helpers.add("call");
|
this.helpers.add("call");
|
||||||
this.insertBlock(`call(this, ${templateVar}, ctx, node, ${key})`, block, {
|
this.insertBlock(`call(this, ${templateVar}, ctx, node, ${key})`, block, {
|
||||||
@@ -3738,7 +3827,7 @@
|
|||||||
else {
|
else {
|
||||||
const id = this.generateId(`callTemplate_`);
|
const id = this.generateId(`callTemplate_`);
|
||||||
this.helpers.add("getTemplate");
|
this.helpers.add("getTemplate");
|
||||||
this.staticCalls.push({ id, template: subTemplate });
|
this.staticDefs.push({ id, expr: `getTemplate(${subTemplate})` });
|
||||||
block = this.createBlock(block, "multi", ctx);
|
block = this.createBlock(block, "multi", ctx);
|
||||||
this.insertBlock(`${id}.call(this, ctx, node, ${key})`, block, {
|
this.insertBlock(`${id}.call(this, ctx, node, ${key})`, block, {
|
||||||
...ctx,
|
...ctx,
|
||||||
@@ -3832,26 +3921,25 @@
|
|||||||
compileComponent(ast, ctx) {
|
compileComponent(ast, ctx) {
|
||||||
let { block } = ctx;
|
let { block } = ctx;
|
||||||
// props
|
// props
|
||||||
const hasSlotsProp = "slots" in ast.props;
|
const hasSlotsProp = "slots" in (ast.props || {});
|
||||||
const props = [];
|
const props = [];
|
||||||
const propExpr = this.formatPropObject(ast.props);
|
const propExpr = this.formatPropObject(ast.props || {});
|
||||||
if (propExpr) {
|
if (propExpr) {
|
||||||
props.push(propExpr);
|
props.push(propExpr);
|
||||||
}
|
}
|
||||||
// slots
|
// slots
|
||||||
const hasSlot = !!Object.keys(ast.slots).length;
|
|
||||||
let slotDef = "";
|
let slotDef = "";
|
||||||
if (hasSlot) {
|
if (ast.slots) {
|
||||||
let ctxStr = "ctx";
|
let ctxStr = "ctx";
|
||||||
if (this.target.loopLevel || !this.hasSafeContext) {
|
if (this.target.loopLevel || !this.hasSafeContext) {
|
||||||
ctxStr = this.generateId("ctx");
|
ctxStr = this.generateId("ctx");
|
||||||
this.helpers.add("capture");
|
this.helpers.add("capture");
|
||||||
this.addLine(`const ${ctxStr} = capture(ctx);`);
|
this.define(ctxStr, `capture(ctx)`);
|
||||||
}
|
}
|
||||||
let slotStr = [];
|
let slotStr = [];
|
||||||
for (let slotName in ast.slots) {
|
for (let slotName in ast.slots) {
|
||||||
const slotAst = ast.slots[slotName].content;
|
const slotAst = ast.slots[slotName];
|
||||||
const name = this.compileInNewTarget("slot", slotAst, ctx);
|
const name = this.compileInNewTarget("slot", slotAst.content, ctx, slotAst.on);
|
||||||
const params = [`__render: ${name}, __ctx: ${ctxStr}`];
|
const params = [`__render: ${name}, __ctx: ${ctxStr}`];
|
||||||
const scope = ast.slots[slotName].scope;
|
const scope = ast.slots[slotName].scope;
|
||||||
if (scope) {
|
if (scope) {
|
||||||
@@ -3877,7 +3965,7 @@
|
|||||||
let propVar;
|
let propVar;
|
||||||
if ((slotDef && (ast.dynamicProps || hasSlotsProp)) || this.dev) {
|
if ((slotDef && (ast.dynamicProps || hasSlotsProp)) || this.dev) {
|
||||||
propVar = this.generateId("props");
|
propVar = this.generateId("props");
|
||||||
this.addLine(`const ${propVar} = ${propString};`);
|
this.define(propVar, propString);
|
||||||
propString = propVar;
|
propString = propVar;
|
||||||
}
|
}
|
||||||
if (slotDef && (ast.dynamicProps || hasSlotsProp)) {
|
if (slotDef && (ast.dynamicProps || hasSlotsProp)) {
|
||||||
@@ -3889,7 +3977,7 @@
|
|||||||
let expr;
|
let expr;
|
||||||
if (ast.isDynamic) {
|
if (ast.isDynamic) {
|
||||||
expr = this.generateId("Comp");
|
expr = this.generateId("Comp");
|
||||||
this.addLine(`let ${expr} = ${compileExpr(ast.name)};`);
|
this.define(expr, compileExpr(ast.name));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
expr = `\`${ast.name}\``;
|
expr = `\`${ast.name}\``;
|
||||||
@@ -3910,9 +3998,28 @@
|
|||||||
if (ast.isDynamic) {
|
if (ast.isDynamic) {
|
||||||
blockExpr = `toggler(${expr}, ${blockExpr})`;
|
blockExpr = `toggler(${expr}, ${blockExpr})`;
|
||||||
}
|
}
|
||||||
|
// event handling
|
||||||
|
if (ast.on) {
|
||||||
|
blockExpr = this.wrapWithEventCatcher(blockExpr, ast.on);
|
||||||
|
}
|
||||||
block = this.createBlock(block, "multi", ctx);
|
block = this.createBlock(block, "multi", ctx);
|
||||||
this.insertBlock(blockExpr, block, ctx);
|
this.insertBlock(blockExpr, block, ctx);
|
||||||
}
|
}
|
||||||
|
wrapWithEventCatcher(expr, on) {
|
||||||
|
this.helpers.add("createCatcher");
|
||||||
|
let name = this.generateId("catcher");
|
||||||
|
let spec = {};
|
||||||
|
let handlers = [];
|
||||||
|
for (let ev in on) {
|
||||||
|
let handlerId = this.generateId("hdlr");
|
||||||
|
let idx = handlers.push(handlerId) - 1;
|
||||||
|
spec[ev] = idx;
|
||||||
|
const handler = this.generateHandlerCode(ev, on[ev]);
|
||||||
|
this.define(handlerId, handler);
|
||||||
|
}
|
||||||
|
this.staticDefs.push({ id: name, expr: `createCatcher(${JSON.stringify(spec)})` });
|
||||||
|
return `${name}(${expr}, [${handlers.join(",")}])`;
|
||||||
|
}
|
||||||
compileTSlot(ast, ctx) {
|
compileTSlot(ast, ctx) {
|
||||||
this.helpers.add("callSlot");
|
this.helpers.add("callSlot");
|
||||||
let { block } = ctx;
|
let { block } = ctx;
|
||||||
@@ -3934,13 +4041,17 @@
|
|||||||
else {
|
else {
|
||||||
if (dynamic) {
|
if (dynamic) {
|
||||||
let name = this.generateId("slot");
|
let name = this.generateId("slot");
|
||||||
this.addLine(`const ${name} = ${slotName};`);
|
this.define(name, slotName);
|
||||||
blockString = `toggler(${name}, callSlot(ctx, node, key, ${name}), ${dynamic}, ${scope})`;
|
blockString = `toggler(${name}, callSlot(ctx, node, key, ${name}), ${dynamic}, ${scope})`;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
blockString = `callSlot(ctx, node, key, ${slotName}, ${dynamic}, ${scope})`;
|
blockString = `callSlot(ctx, node, key, ${slotName}, ${dynamic}, ${scope})`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// event handling
|
||||||
|
if (ast.on) {
|
||||||
|
blockString = this.wrapWithEventCatcher(blockString, ast.on);
|
||||||
|
}
|
||||||
if (block) {
|
if (block) {
|
||||||
this.insertAnchor(block);
|
this.insertAnchor(block);
|
||||||
}
|
}
|
||||||
@@ -3961,7 +4072,7 @@
|
|||||||
if (this.target.loopLevel || !this.hasSafeContext) {
|
if (this.target.loopLevel || !this.hasSafeContext) {
|
||||||
ctxStr = this.generateId("ctx");
|
ctxStr = this.generateId("ctx");
|
||||||
this.helpers.add("capture");
|
this.helpers.add("capture");
|
||||||
this.addLine(`const ${ctxStr} = capture(ctx);`);
|
this.define(ctxStr, `capture(ctx);`);
|
||||||
}
|
}
|
||||||
const blockString = `component(Portal, {target: ${ast.target},slots: {'default': {__render: ${name}, __ctx: ${ctxStr}}}}, key + \`${key}\`, node, ctx)`;
|
const blockString = `component(Portal, {target: ${ast.target},slots: {'default': {__render: ${name}, __ctx: ${ctxStr}}}}, key + \`${key}\`, node, ctx)`;
|
||||||
if (block) {
|
if (block) {
|
||||||
@@ -4095,8 +4206,8 @@
|
|||||||
const ref = node.getAttribute("t-ref");
|
const ref = node.getAttribute("t-ref");
|
||||||
node.removeAttribute("t-ref");
|
node.removeAttribute("t-ref");
|
||||||
const nodeAttrsNames = node.getAttributeNames();
|
const nodeAttrsNames = node.getAttributeNames();
|
||||||
const attrs = {};
|
let attrs = null;
|
||||||
const on = {};
|
let on = null;
|
||||||
let model = null;
|
let model = null;
|
||||||
for (let attr of nodeAttrsNames) {
|
for (let attr of nodeAttrsNames) {
|
||||||
const value = node.getAttribute(attr);
|
const value = node.getAttribute(attr);
|
||||||
@@ -4104,6 +4215,7 @@
|
|||||||
if (attr === "t-on") {
|
if (attr === "t-on") {
|
||||||
throw new Error("Missing event name with t-on directive");
|
throw new Error("Missing event name with t-on directive");
|
||||||
}
|
}
|
||||||
|
on = on || {};
|
||||||
on[attr.slice(5)] = value;
|
on[attr.slice(5)] = value;
|
||||||
}
|
}
|
||||||
else if (attr.startsWith("t-model")) {
|
else if (attr.startsWith("t-model")) {
|
||||||
@@ -4141,6 +4253,7 @@
|
|||||||
targetAttr: isCheckboxInput ? "checked" : "value",
|
targetAttr: isCheckboxInput ? "checked" : "value",
|
||||||
specialInitTargetAttr: isRadioInput ? "checked" : null,
|
specialInitTargetAttr: isRadioInput ? "checked" : null,
|
||||||
eventType,
|
eventType,
|
||||||
|
hasDynamicChildren: false,
|
||||||
shouldTrim: hasTrimMod && (isOtherInput || isTextarea),
|
shouldTrim: hasTrimMod && (isOtherInput || isTextarea),
|
||||||
shouldNumberize: hasNumberMod && (isOtherInput || isTextarea),
|
shouldNumberize: hasNumberMod && (isOtherInput || isTextarea),
|
||||||
};
|
};
|
||||||
@@ -4161,6 +4274,7 @@
|
|||||||
if (tModel && ["t-att-value", "t-attf-value"].includes(attr)) {
|
if (tModel && ["t-att-value", "t-attf-value"].includes(attr)) {
|
||||||
tModel.hasDynamicChildren = true;
|
tModel.hasDynamicChildren = true;
|
||||||
}
|
}
|
||||||
|
attrs = attrs || {};
|
||||||
attrs[attr] = value;
|
attrs[attr] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4311,7 +4425,7 @@
|
|||||||
if (ast && ast.type === 11 /* TComponent */) {
|
if (ast && ast.type === 11 /* TComponent */) {
|
||||||
return {
|
return {
|
||||||
...ast,
|
...ast,
|
||||||
slots: { default: { content: tcall } },
|
slots: { default: { content: tcall, scope: null, on: null, attrs: null } },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4395,7 +4509,6 @@
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Error messages when trying to use an unsupported directive on a component
|
// Error messages when trying to use an unsupported directive on a component
|
||||||
const directiveErrorMap = new Map([
|
const directiveErrorMap = new Map([
|
||||||
["t-on", "t-on is no longer supported on components. Consider passing a callback in props."],
|
|
||||||
[
|
[
|
||||||
"t-ref",
|
"t-ref",
|
||||||
"t-ref is no longer supported on components. Consider exposing only the public part of the component's API through a callback prop.",
|
"t-ref is no longer supported on components. Consider exposing only the public part of the component's API through a callback prop.",
|
||||||
@@ -4424,18 +4537,26 @@
|
|||||||
node.removeAttribute("t-props");
|
node.removeAttribute("t-props");
|
||||||
const defaultSlotScope = node.getAttribute("t-slot-scope");
|
const defaultSlotScope = node.getAttribute("t-slot-scope");
|
||||||
node.removeAttribute("t-slot-scope");
|
node.removeAttribute("t-slot-scope");
|
||||||
const props = {};
|
let on = null;
|
||||||
|
let props = null;
|
||||||
for (let name of node.getAttributeNames()) {
|
for (let name of node.getAttributeNames()) {
|
||||||
const value = node.getAttribute(name);
|
const value = node.getAttribute(name);
|
||||||
if (name.startsWith("t-")) {
|
if (name.startsWith("t-")) {
|
||||||
const message = directiveErrorMap.get(name.split("-").slice(0, 2).join("-"));
|
if (name.startsWith("t-on-")) {
|
||||||
throw new Error(message || `unsupported directive on Component: ${name}`);
|
on = on || {};
|
||||||
|
on[name.slice(5)] = value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const message = directiveErrorMap.get(name.split("-").slice(0, 2).join("-"));
|
||||||
|
throw new Error(message || `unsupported directive on Component: ${name}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
props = props || {};
|
||||||
props[name] = value;
|
props[name] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const slots = {};
|
let slots = null;
|
||||||
if (node.hasChildNodes()) {
|
if (node.hasChildNodes()) {
|
||||||
const clone = node.cloneNode(true);
|
const clone = node.cloneNode(true);
|
||||||
// named slots
|
// named slots
|
||||||
@@ -4463,32 +4584,36 @@
|
|||||||
slotNode.remove();
|
slotNode.remove();
|
||||||
const slotAst = parseNode(slotNode, ctx);
|
const slotAst = parseNode(slotNode, ctx);
|
||||||
if (slotAst) {
|
if (slotAst) {
|
||||||
const slotInfo = { content: slotAst };
|
let on = null;
|
||||||
const attrs = {};
|
let attrs = null;
|
||||||
|
let scope = null;
|
||||||
for (let attributeName of slotNode.getAttributeNames()) {
|
for (let attributeName of slotNode.getAttributeNames()) {
|
||||||
const value = slotNode.getAttribute(attributeName);
|
const value = slotNode.getAttribute(attributeName);
|
||||||
if (attributeName === "t-slot-scope") {
|
if (attributeName === "t-slot-scope") {
|
||||||
slotInfo.scope = value;
|
scope = value;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
attrs[attributeName] = value;
|
else if (attributeName.startsWith("t-on-")) {
|
||||||
|
on = on || {};
|
||||||
|
on[attributeName.slice(5)] = value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
attrs = attrs || {};
|
||||||
|
attrs[attributeName] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (Object.keys(attrs).length) {
|
slots = slots || {};
|
||||||
slotInfo.attrs = attrs;
|
slots[name] = { content: slotAst, on, attrs, scope };
|
||||||
}
|
|
||||||
slots[name] = slotInfo;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// default slot
|
// default slot
|
||||||
const defaultContent = parseChildNodes(clone, ctx);
|
const defaultContent = parseChildNodes(clone, ctx);
|
||||||
if (defaultContent) {
|
if (defaultContent) {
|
||||||
slots.default = { content: defaultContent };
|
slots = slots || {};
|
||||||
if (defaultSlotScope) {
|
slots.default = { content: defaultContent, on, attrs: null, scope: defaultSlotScope };
|
||||||
slots.default.scope = defaultSlotScope;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { type: 11 /* TComponent */, name, isDynamic, dynamicProps, props, slots };
|
return { type: 11 /* TComponent */, name, isDynamic, dynamicProps, props, slots, on };
|
||||||
}
|
}
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Slots
|
// Slots
|
||||||
@@ -4499,15 +4624,24 @@
|
|||||||
}
|
}
|
||||||
const name = node.getAttribute("t-slot");
|
const name = node.getAttribute("t-slot");
|
||||||
node.removeAttribute("t-slot");
|
node.removeAttribute("t-slot");
|
||||||
const attrs = {};
|
let attrs = null;
|
||||||
|
let on = null;
|
||||||
for (let attributeName of node.getAttributeNames()) {
|
for (let attributeName of node.getAttributeNames()) {
|
||||||
const value = node.getAttribute(attributeName);
|
const value = node.getAttribute(attributeName);
|
||||||
attrs[attributeName] = value;
|
if (attributeName.startsWith("t-on-")) {
|
||||||
|
on = on || {};
|
||||||
|
on[attributeName.slice(5)] = value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
attrs = attrs || {};
|
||||||
|
attrs[attributeName] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: 14 /* TSlot */,
|
type: 14 /* TSlot */,
|
||||||
name,
|
name,
|
||||||
attrs,
|
attrs,
|
||||||
|
on,
|
||||||
defaultContent: parseChildNodes(node, ctx),
|
defaultContent: parseChildNodes(node, ctx),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -4767,20 +4901,22 @@
|
|||||||
const node = getCurrent();
|
const node = getCurrent();
|
||||||
const renderFn = node.renderFn;
|
const renderFn = node.renderFn;
|
||||||
const decorate = node.app.dev ? wrapError : (fn) => fn;
|
const decorate = node.app.dev ? wrapError : (fn) => fn;
|
||||||
node.renderFn = decorate(() => {
|
fn = decorate(fn.bind(node.component), "onWillRender");
|
||||||
fn.call(node.component);
|
node.renderFn = () => {
|
||||||
|
fn();
|
||||||
return renderFn();
|
return renderFn();
|
||||||
}, "onWillRender");
|
};
|
||||||
}
|
}
|
||||||
function onRendered(fn) {
|
function onRendered(fn) {
|
||||||
const node = getCurrent();
|
const node = getCurrent();
|
||||||
const renderFn = node.renderFn;
|
const renderFn = node.renderFn;
|
||||||
const decorate = node.app.dev ? wrapError : (fn) => fn;
|
const decorate = node.app.dev ? wrapError : (fn) => fn;
|
||||||
node.renderFn = decorate(() => {
|
fn = decorate(fn.bind(node.component), "onRendered");
|
||||||
|
node.renderFn = () => {
|
||||||
const result = renderFn();
|
const result = renderFn();
|
||||||
fn.call(node.component);
|
fn();
|
||||||
return result;
|
return result;
|
||||||
}, "onRendered");
|
};
|
||||||
}
|
}
|
||||||
function onError(callback) {
|
function onError(callback) {
|
||||||
const node = getCurrent();
|
const node = getCurrent();
|
||||||
@@ -4882,7 +5018,7 @@
|
|||||||
const { __render, __ctx, __scope } = slots[name] || {};
|
const { __render, __ctx, __scope } = slots[name] || {};
|
||||||
const slotScope = Object.create(__ctx || {});
|
const slotScope = Object.create(__ctx || {});
|
||||||
if (__scope) {
|
if (__scope) {
|
||||||
slotScope[__scope] = extra || {};
|
slotScope[__scope] = extra;
|
||||||
}
|
}
|
||||||
const slotBDom = __render ? __render.call(__ctx.__owl__.component, slotScope, parent, key) : null;
|
const slotBDom = __render ? __render.call(__ctx.__owl__.component, slotScope, parent, key) : null;
|
||||||
if (defaultContent) {
|
if (defaultContent) {
|
||||||
@@ -5038,6 +5174,7 @@
|
|||||||
LazyValue,
|
LazyValue,
|
||||||
safeOutput,
|
safeOutput,
|
||||||
bind,
|
bind,
|
||||||
|
createCatcher,
|
||||||
};
|
};
|
||||||
|
|
||||||
const bdom = { text, createBlock, list, multi, html, toggler, component, comment };
|
const bdom = { text, createBlock, list, multi, html, toggler, component, comment };
|
||||||
@@ -5390,9 +5527,9 @@ See https://github.com/odoo/owl/blob/${hash}/doc/reference/app.md#configuration
|
|||||||
Object.defineProperty(exports, '__esModule', { value: true });
|
Object.defineProperty(exports, '__esModule', { value: true });
|
||||||
|
|
||||||
|
|
||||||
__info__.version = '2.0.0-beta.2';
|
__info__.version = '2.0.0-beta.3';
|
||||||
__info__.date = '2022-03-03T15:22:20.282Z';
|
__info__.date = '2022-03-08T11:47:57.414Z';
|
||||||
__info__.hash = 'e4fdd32';
|
__info__.hash = 'c356351';
|
||||||
__info__.url = 'https://github.com/odoo/owl';
|
__info__.url = 'https://github.com/odoo/owl';
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user