[IMP] update owl to v2.0.0-beta.3

This commit is contained in:
Samuel Degueldre
2022-03-08 12:48:05 +01:00
parent 9d3ef2b541
commit db41b28d9c
+230 -93
View File
@@ -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';