@odoo/owl 2.0.0-beta.2 → 2.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +766 -0
- package/dist/owl.cjs.js +230 -93
- package/dist/owl.cjs.min.js +1 -1
- package/dist/owl.es.js +230 -93
- package/dist/owl.es.min.js +1 -1
- package/dist/owl.iife.js +230 -93
- package/dist/owl.iife.min.js +1 -1
- package/dist/types/app/template_helpers.d.ts +2 -1
- package/dist/types/blockdom/event_catcher.d.ts +7 -0
- package/dist/types/blockdom/events.d.ts +1 -0
- package/dist/types/blockdom/index.d.ts +1 -0
- package/dist/types/compiler/code_generator.d.ts +9 -6
- package/dist/types/compiler/parser.d.ts +25 -23
- package/package.json +1 -1
package/dist/owl.iife.js
CHANGED
|
@@ -266,10 +266,14 @@
|
|
|
266
266
|
this[eventKey] = data;
|
|
267
267
|
this.addEventListener(evName, listener, { capture });
|
|
268
268
|
}
|
|
269
|
+
function remove() {
|
|
270
|
+
delete this[eventKey];
|
|
271
|
+
this.removeEventListener(evName, listener, { capture });
|
|
272
|
+
}
|
|
269
273
|
function update(data) {
|
|
270
274
|
this[eventKey] = data;
|
|
271
275
|
}
|
|
272
|
-
return { setup, update };
|
|
276
|
+
return { setup, update, remove };
|
|
273
277
|
}
|
|
274
278
|
// Synthetic handler: a form of event delegation that allows placing only one
|
|
275
279
|
// listener per event type.
|
|
@@ -286,7 +290,10 @@
|
|
|
286
290
|
_data[currentId] = data;
|
|
287
291
|
this[eventKey] = _data;
|
|
288
292
|
}
|
|
289
|
-
|
|
293
|
+
function remove() {
|
|
294
|
+
delete this[eventKey];
|
|
295
|
+
}
|
|
296
|
+
return { setup, update: setup, remove };
|
|
290
297
|
}
|
|
291
298
|
function nativeToSyntheticEvent(eventKey, event) {
|
|
292
299
|
let dom = event.target;
|
|
@@ -1281,6 +1288,75 @@
|
|
|
1281
1288
|
return new VHtml(str);
|
|
1282
1289
|
}
|
|
1283
1290
|
|
|
1291
|
+
function createCatcher(eventsSpec) {
|
|
1292
|
+
let setupFns = [];
|
|
1293
|
+
let removeFns = [];
|
|
1294
|
+
for (let name in eventsSpec) {
|
|
1295
|
+
let index = eventsSpec[name];
|
|
1296
|
+
let { setup, remove } = createEventHandler(name);
|
|
1297
|
+
setupFns[index] = setup;
|
|
1298
|
+
removeFns[index] = remove;
|
|
1299
|
+
}
|
|
1300
|
+
let n = setupFns.length;
|
|
1301
|
+
class VCatcher {
|
|
1302
|
+
constructor(child, handlers) {
|
|
1303
|
+
this.afterNode = null;
|
|
1304
|
+
this.child = child;
|
|
1305
|
+
this.handlers = handlers;
|
|
1306
|
+
}
|
|
1307
|
+
mount(parent, afterNode) {
|
|
1308
|
+
this.parentEl = parent;
|
|
1309
|
+
this.afterNode = afterNode;
|
|
1310
|
+
this.child.mount(parent, afterNode);
|
|
1311
|
+
for (let i = 0; i < n; i++) {
|
|
1312
|
+
let origFn = this.handlers[i][0];
|
|
1313
|
+
const self = this;
|
|
1314
|
+
this.handlers[i][0] = function (ev) {
|
|
1315
|
+
const target = ev.target;
|
|
1316
|
+
let currentNode = self.child.firstNode();
|
|
1317
|
+
const afterNode = self.afterNode;
|
|
1318
|
+
while (currentNode !== afterNode) {
|
|
1319
|
+
if (currentNode.contains(target)) {
|
|
1320
|
+
return origFn.call(this, ev);
|
|
1321
|
+
}
|
|
1322
|
+
currentNode = currentNode.nextSibling;
|
|
1323
|
+
}
|
|
1324
|
+
};
|
|
1325
|
+
setupFns[i].call(parent, this.handlers[i]);
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
moveBefore(other, afterNode) {
|
|
1329
|
+
this.afterNode = null;
|
|
1330
|
+
this.child.moveBefore(other ? other.child : null, afterNode);
|
|
1331
|
+
}
|
|
1332
|
+
patch(other, withBeforeRemove) {
|
|
1333
|
+
if (this === other) {
|
|
1334
|
+
return;
|
|
1335
|
+
}
|
|
1336
|
+
this.handlers = other.handlers;
|
|
1337
|
+
this.child.patch(other.child, withBeforeRemove);
|
|
1338
|
+
}
|
|
1339
|
+
beforeRemove() {
|
|
1340
|
+
this.child.beforeRemove();
|
|
1341
|
+
}
|
|
1342
|
+
remove() {
|
|
1343
|
+
for (let i = 0; i < n; i++) {
|
|
1344
|
+
removeFns[i].call(this.parentEl);
|
|
1345
|
+
}
|
|
1346
|
+
this.child.remove();
|
|
1347
|
+
}
|
|
1348
|
+
firstNode() {
|
|
1349
|
+
return this.child.firstNode();
|
|
1350
|
+
}
|
|
1351
|
+
toString() {
|
|
1352
|
+
return this.child.toString();
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
return function (child, handlers) {
|
|
1356
|
+
return new VCatcher(child, handlers);
|
|
1357
|
+
};
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1284
1360
|
function mount$1(vnode, fixture, afterNode = null) {
|
|
1285
1361
|
vnode.mount(fixture, afterNode);
|
|
1286
1362
|
}
|
|
@@ -2733,24 +2809,31 @@
|
|
|
2733
2809
|
function tokenize(expr) {
|
|
2734
2810
|
const result = [];
|
|
2735
2811
|
let token = true;
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2812
|
+
let error;
|
|
2813
|
+
let current = expr;
|
|
2814
|
+
try {
|
|
2815
|
+
while (token) {
|
|
2816
|
+
current = current.trim();
|
|
2817
|
+
if (current) {
|
|
2818
|
+
for (let tokenizer of TOKENIZERS) {
|
|
2819
|
+
token = tokenizer(current);
|
|
2820
|
+
if (token) {
|
|
2821
|
+
result.push(token);
|
|
2822
|
+
current = current.slice(token.size || token.value.length);
|
|
2823
|
+
break;
|
|
2824
|
+
}
|
|
2745
2825
|
}
|
|
2746
2826
|
}
|
|
2827
|
+
else {
|
|
2828
|
+
token = false;
|
|
2829
|
+
}
|
|
2747
2830
|
}
|
|
2748
|
-
else {
|
|
2749
|
-
token = false;
|
|
2750
|
-
}
|
|
2751
2831
|
}
|
|
2752
|
-
|
|
2753
|
-
|
|
2832
|
+
catch (e) {
|
|
2833
|
+
error = e; // Silence all errors and throw a generic error below
|
|
2834
|
+
}
|
|
2835
|
+
if (current.length || error) {
|
|
2836
|
+
throw new Error(`Tokenizer error: could not tokenize \`${expr}\``);
|
|
2754
2837
|
}
|
|
2755
2838
|
return result;
|
|
2756
2839
|
}
|
|
@@ -2955,7 +3038,7 @@
|
|
|
2955
3038
|
}, params);
|
|
2956
3039
|
}
|
|
2957
3040
|
class CodeTarget {
|
|
2958
|
-
constructor(name) {
|
|
3041
|
+
constructor(name, on) {
|
|
2959
3042
|
this.indentLevel = 0;
|
|
2960
3043
|
this.loopLevel = 0;
|
|
2961
3044
|
this.code = [];
|
|
@@ -2966,6 +3049,7 @@
|
|
|
2966
3049
|
this.refInfo = {};
|
|
2967
3050
|
this.shouldProtectScope = false;
|
|
2968
3051
|
this.name = name;
|
|
3052
|
+
this.on = on || null;
|
|
2969
3053
|
}
|
|
2970
3054
|
addLine(line, idx) {
|
|
2971
3055
|
const prefix = new Array(this.indentLevel + 2).join(" ");
|
|
@@ -3015,7 +3099,7 @@
|
|
|
3015
3099
|
this.targets = [];
|
|
3016
3100
|
this.target = new CodeTarget("template");
|
|
3017
3101
|
this.translatableAttributes = TRANSLATABLE_ATTRS;
|
|
3018
|
-
this.
|
|
3102
|
+
this.staticDefs = [];
|
|
3019
3103
|
this.helpers = new Set();
|
|
3020
3104
|
this.translateFn = options.translateFn || ((s) => s);
|
|
3021
3105
|
if (options.translatableAttributes) {
|
|
@@ -3058,8 +3142,8 @@
|
|
|
3058
3142
|
if (this.templateName) {
|
|
3059
3143
|
mainCode.push(`// Template name: "${this.templateName}"`);
|
|
3060
3144
|
}
|
|
3061
|
-
for (let { id,
|
|
3062
|
-
mainCode.push(`const ${id} =
|
|
3145
|
+
for (let { id, expr } of this.staticDefs) {
|
|
3146
|
+
mainCode.push(`const ${id} = ${expr};`);
|
|
3063
3147
|
}
|
|
3064
3148
|
// define all blocks
|
|
3065
3149
|
if (this.blocks.length) {
|
|
@@ -3095,19 +3179,21 @@
|
|
|
3095
3179
|
}
|
|
3096
3180
|
return code;
|
|
3097
3181
|
}
|
|
3098
|
-
compileInNewTarget(prefix, ast, ctx) {
|
|
3182
|
+
compileInNewTarget(prefix, ast, ctx, on) {
|
|
3099
3183
|
const name = this.generateId(prefix);
|
|
3100
3184
|
const initialTarget = this.target;
|
|
3101
|
-
const target = new CodeTarget(name);
|
|
3185
|
+
const target = new CodeTarget(name, on);
|
|
3102
3186
|
this.targets.push(target);
|
|
3103
3187
|
this.target = target;
|
|
3104
|
-
|
|
3105
|
-
this.compileAST(ast, subCtx);
|
|
3188
|
+
this.compileAST(ast, createContext(ctx));
|
|
3106
3189
|
this.target = initialTarget;
|
|
3107
3190
|
return name;
|
|
3108
3191
|
}
|
|
3109
|
-
addLine(line) {
|
|
3110
|
-
this.target.addLine(line);
|
|
3192
|
+
addLine(line, idx) {
|
|
3193
|
+
this.target.addLine(line, idx);
|
|
3194
|
+
}
|
|
3195
|
+
define(varName, expr) {
|
|
3196
|
+
this.addLine(`const ${varName} = ${expr};`);
|
|
3111
3197
|
}
|
|
3112
3198
|
generateId(prefix = "") {
|
|
3113
3199
|
this.ids[prefix] = (this.ids[prefix] || 0) + 1;
|
|
@@ -3149,10 +3235,13 @@
|
|
|
3149
3235
|
blockExpr = `toggler(${tKeyExpr}, ${blockExpr})`;
|
|
3150
3236
|
}
|
|
3151
3237
|
if (block.isRoot && !ctx.preventRoot) {
|
|
3238
|
+
if (this.target.on) {
|
|
3239
|
+
blockExpr = this.wrapWithEventCatcher(blockExpr, this.target.on);
|
|
3240
|
+
}
|
|
3152
3241
|
this.addLine(`return ${blockExpr};`);
|
|
3153
3242
|
}
|
|
3154
3243
|
else {
|
|
3155
|
-
this.
|
|
3244
|
+
this.define(block.varName, blockExpr);
|
|
3156
3245
|
}
|
|
3157
3246
|
}
|
|
3158
3247
|
/**
|
|
@@ -3180,7 +3269,7 @@
|
|
|
3180
3269
|
if (!mapping.has(tok.varName)) {
|
|
3181
3270
|
const varId = this.generateId("v");
|
|
3182
3271
|
mapping.set(tok.varName, varId);
|
|
3183
|
-
this.
|
|
3272
|
+
this.define(varId, tok.value);
|
|
3184
3273
|
}
|
|
3185
3274
|
tok.value = mapping.get(tok.varName);
|
|
3186
3275
|
}
|
|
@@ -3319,7 +3408,7 @@
|
|
|
3319
3408
|
this.blocks.push(block);
|
|
3320
3409
|
if (ast.dynamicTag) {
|
|
3321
3410
|
const tagExpr = this.generateId("tag");
|
|
3322
|
-
this.
|
|
3411
|
+
this.define(tagExpr, compileExpr(ast.dynamicTag));
|
|
3323
3412
|
block.dynamicTagName = tagExpr;
|
|
3324
3413
|
}
|
|
3325
3414
|
}
|
|
@@ -3401,10 +3490,10 @@
|
|
|
3401
3490
|
const { hasDynamicChildren, baseExpr, expr, eventType, shouldNumberize, shouldTrim, targetAttr, specialInitTargetAttr, } = ast.model;
|
|
3402
3491
|
const baseExpression = compileExpr(baseExpr);
|
|
3403
3492
|
const bExprId = this.generateId("bExpr");
|
|
3404
|
-
this.
|
|
3493
|
+
this.define(bExprId, baseExpression);
|
|
3405
3494
|
const expression = compileExpr(expr);
|
|
3406
3495
|
const exprId = this.generateId("expr");
|
|
3407
|
-
this.
|
|
3496
|
+
this.define(exprId, expression);
|
|
3408
3497
|
const fullExpression = `${bExprId}[${exprId}]`;
|
|
3409
3498
|
let idx;
|
|
3410
3499
|
if (specialInitTargetAttr) {
|
|
@@ -3414,7 +3503,7 @@
|
|
|
3414
3503
|
else if (hasDynamicChildren) {
|
|
3415
3504
|
const bValueId = this.generateId("bValue");
|
|
3416
3505
|
tModelSelectedExpr = `${bValueId}`;
|
|
3417
|
-
this.
|
|
3506
|
+
this.define(tModelSelectedExpr, fullExpression);
|
|
3418
3507
|
}
|
|
3419
3508
|
else {
|
|
3420
3509
|
idx = block.insertData(`${fullExpression}`, "attr");
|
|
@@ -3462,14 +3551,14 @@
|
|
|
3462
3551
|
const children = block.children.slice();
|
|
3463
3552
|
let current = children.shift();
|
|
3464
3553
|
for (let i = codeIdx; i < code.length; i++) {
|
|
3465
|
-
if (code[i].trimStart().startsWith(`
|
|
3466
|
-
code[i] = code[i].replace(`
|
|
3554
|
+
if (code[i].trimStart().startsWith(`const ${current.varName} `)) {
|
|
3555
|
+
code[i] = code[i].replace(`const ${current.varName}`, current.varName);
|
|
3467
3556
|
current = children.shift();
|
|
3468
3557
|
if (!current)
|
|
3469
3558
|
break;
|
|
3470
3559
|
}
|
|
3471
3560
|
}
|
|
3472
|
-
this.
|
|
3561
|
+
this.addLine(`let ${block.children.map((c) => c.varName)};`, codeIdx);
|
|
3473
3562
|
}
|
|
3474
3563
|
}
|
|
3475
3564
|
}
|
|
@@ -3557,14 +3646,14 @@
|
|
|
3557
3646
|
const children = block.children.slice();
|
|
3558
3647
|
let current = children.shift();
|
|
3559
3648
|
for (let i = codeIdx; i < code.length; i++) {
|
|
3560
|
-
if (code[i].trimStart().startsWith(`
|
|
3561
|
-
code[i] = code[i].replace(`
|
|
3649
|
+
if (code[i].trimStart().startsWith(`const ${current.varName} `)) {
|
|
3650
|
+
code[i] = code[i].replace(`const ${current.varName}`, current.varName);
|
|
3562
3651
|
current = children.shift();
|
|
3563
3652
|
if (!current)
|
|
3564
3653
|
break;
|
|
3565
3654
|
}
|
|
3566
3655
|
}
|
|
3567
|
-
this.
|
|
3656
|
+
this.addLine(`let ${block.children.map((c) => c.varName)};`, codeIdx);
|
|
3568
3657
|
}
|
|
3569
3658
|
// note: this part is duplicated from end of compilemulti:
|
|
3570
3659
|
const args = block.children.map((c) => c.varName).join(", ");
|
|
@@ -3585,10 +3674,10 @@
|
|
|
3585
3674
|
const l = `l_block${block.id}`;
|
|
3586
3675
|
const c = `c_block${block.id}`;
|
|
3587
3676
|
this.helpers.add("prepareList");
|
|
3588
|
-
this.
|
|
3677
|
+
this.define(`[${keys}, ${vals}, ${l}, ${c}]`, `prepareList(${compileExpr(ast.collection)});`);
|
|
3589
3678
|
// Throw errors on duplicate keys in dev mode
|
|
3590
3679
|
if (this.dev) {
|
|
3591
|
-
this.
|
|
3680
|
+
this.define(`keys${block.id}`, `new Set()`);
|
|
3592
3681
|
}
|
|
3593
3682
|
this.addLine(`for (let ${loopVar} = 0; ${loopVar} < ${l}; ${loopVar}++) {`);
|
|
3594
3683
|
this.target.indentLevel++;
|
|
@@ -3605,7 +3694,7 @@
|
|
|
3605
3694
|
if (!ast.hasNoValue) {
|
|
3606
3695
|
this.addLine(`ctx[\`${ast.elem}_value\`] = ${keys}[${loopVar}];`);
|
|
3607
3696
|
}
|
|
3608
|
-
this.
|
|
3697
|
+
this.define(`key${this.target.loopLevel}`, ast.key ? compileExpr(ast.key) : loopVar);
|
|
3609
3698
|
if (this.dev) {
|
|
3610
3699
|
// Throw error on duplicate keys in dev mode
|
|
3611
3700
|
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 @@
|
|
|
3615
3704
|
if (ast.memo) {
|
|
3616
3705
|
this.target.hasCache = true;
|
|
3617
3706
|
id = this.generateId();
|
|
3618
|
-
this.
|
|
3619
|
-
this.
|
|
3707
|
+
this.define(`memo${id}`, compileExpr(ast.memo));
|
|
3708
|
+
this.define(`vnode${id}`, `cache[key${this.target.loopLevel}];`);
|
|
3620
3709
|
this.addLine(`if (vnode${id}) {`);
|
|
3621
3710
|
this.target.indentLevel++;
|
|
3622
3711
|
this.addLine(`if (shallowEqual(vnode${id}.memo, memo${id})) {`);
|
|
@@ -3644,7 +3733,7 @@
|
|
|
3644
3733
|
}
|
|
3645
3734
|
compileTKey(ast, ctx) {
|
|
3646
3735
|
const tKeyExpr = this.generateId("tKey_");
|
|
3647
|
-
this.
|
|
3736
|
+
this.define(tKeyExpr, compileExpr(ast.expr));
|
|
3648
3737
|
ctx = createContext(ctx, {
|
|
3649
3738
|
tKeyExpr,
|
|
3650
3739
|
block: ctx.block,
|
|
@@ -3689,14 +3778,14 @@
|
|
|
3689
3778
|
const children = block.children.slice();
|
|
3690
3779
|
let current = children.shift();
|
|
3691
3780
|
for (let i = codeIdx; i < code.length; i++) {
|
|
3692
|
-
if (code[i].trimStart().startsWith(`
|
|
3693
|
-
code[i] = code[i].replace(`
|
|
3781
|
+
if (code[i].trimStart().startsWith(`const ${current.varName} `)) {
|
|
3782
|
+
code[i] = code[i].replace(`const ${current.varName}`, current.varName);
|
|
3694
3783
|
current = children.shift();
|
|
3695
3784
|
if (!current)
|
|
3696
3785
|
break;
|
|
3697
3786
|
}
|
|
3698
3787
|
}
|
|
3699
|
-
this.
|
|
3788
|
+
this.addLine(`let ${block.children.map((c) => c.varName)};`, codeIdx);
|
|
3700
3789
|
}
|
|
3701
3790
|
}
|
|
3702
3791
|
const args = block.children.map((c) => c.varName).join(", ");
|
|
@@ -3727,7 +3816,7 @@
|
|
|
3727
3816
|
const key = `key + \`${this.generateComponentKey()}\``;
|
|
3728
3817
|
if (isDynamic) {
|
|
3729
3818
|
const templateVar = this.generateId("template");
|
|
3730
|
-
this.
|
|
3819
|
+
this.define(templateVar, subTemplate);
|
|
3731
3820
|
block = this.createBlock(block, "multi", ctx);
|
|
3732
3821
|
this.helpers.add("call");
|
|
3733
3822
|
this.insertBlock(`call(this, ${templateVar}, ctx, node, ${key})`, block, {
|
|
@@ -3738,7 +3827,7 @@
|
|
|
3738
3827
|
else {
|
|
3739
3828
|
const id = this.generateId(`callTemplate_`);
|
|
3740
3829
|
this.helpers.add("getTemplate");
|
|
3741
|
-
this.
|
|
3830
|
+
this.staticDefs.push({ id, expr: `getTemplate(${subTemplate})` });
|
|
3742
3831
|
block = this.createBlock(block, "multi", ctx);
|
|
3743
3832
|
this.insertBlock(`${id}.call(this, ctx, node, ${key})`, block, {
|
|
3744
3833
|
...ctx,
|
|
@@ -3832,26 +3921,25 @@
|
|
|
3832
3921
|
compileComponent(ast, ctx) {
|
|
3833
3922
|
let { block } = ctx;
|
|
3834
3923
|
// props
|
|
3835
|
-
const hasSlotsProp = "slots" in ast.props;
|
|
3924
|
+
const hasSlotsProp = "slots" in (ast.props || {});
|
|
3836
3925
|
const props = [];
|
|
3837
|
-
const propExpr = this.formatPropObject(ast.props);
|
|
3926
|
+
const propExpr = this.formatPropObject(ast.props || {});
|
|
3838
3927
|
if (propExpr) {
|
|
3839
3928
|
props.push(propExpr);
|
|
3840
3929
|
}
|
|
3841
3930
|
// slots
|
|
3842
|
-
const hasSlot = !!Object.keys(ast.slots).length;
|
|
3843
3931
|
let slotDef = "";
|
|
3844
|
-
if (
|
|
3932
|
+
if (ast.slots) {
|
|
3845
3933
|
let ctxStr = "ctx";
|
|
3846
3934
|
if (this.target.loopLevel || !this.hasSafeContext) {
|
|
3847
3935
|
ctxStr = this.generateId("ctx");
|
|
3848
3936
|
this.helpers.add("capture");
|
|
3849
|
-
this.
|
|
3937
|
+
this.define(ctxStr, `capture(ctx)`);
|
|
3850
3938
|
}
|
|
3851
3939
|
let slotStr = [];
|
|
3852
3940
|
for (let slotName in ast.slots) {
|
|
3853
|
-
const slotAst = ast.slots[slotName]
|
|
3854
|
-
const name = this.compileInNewTarget("slot", slotAst, ctx);
|
|
3941
|
+
const slotAst = ast.slots[slotName];
|
|
3942
|
+
const name = this.compileInNewTarget("slot", slotAst.content, ctx, slotAst.on);
|
|
3855
3943
|
const params = [`__render: ${name}, __ctx: ${ctxStr}`];
|
|
3856
3944
|
const scope = ast.slots[slotName].scope;
|
|
3857
3945
|
if (scope) {
|
|
@@ -3877,7 +3965,7 @@
|
|
|
3877
3965
|
let propVar;
|
|
3878
3966
|
if ((slotDef && (ast.dynamicProps || hasSlotsProp)) || this.dev) {
|
|
3879
3967
|
propVar = this.generateId("props");
|
|
3880
|
-
this.
|
|
3968
|
+
this.define(propVar, propString);
|
|
3881
3969
|
propString = propVar;
|
|
3882
3970
|
}
|
|
3883
3971
|
if (slotDef && (ast.dynamicProps || hasSlotsProp)) {
|
|
@@ -3889,7 +3977,7 @@
|
|
|
3889
3977
|
let expr;
|
|
3890
3978
|
if (ast.isDynamic) {
|
|
3891
3979
|
expr = this.generateId("Comp");
|
|
3892
|
-
this.
|
|
3980
|
+
this.define(expr, compileExpr(ast.name));
|
|
3893
3981
|
}
|
|
3894
3982
|
else {
|
|
3895
3983
|
expr = `\`${ast.name}\``;
|
|
@@ -3910,9 +3998,28 @@
|
|
|
3910
3998
|
if (ast.isDynamic) {
|
|
3911
3999
|
blockExpr = `toggler(${expr}, ${blockExpr})`;
|
|
3912
4000
|
}
|
|
4001
|
+
// event handling
|
|
4002
|
+
if (ast.on) {
|
|
4003
|
+
blockExpr = this.wrapWithEventCatcher(blockExpr, ast.on);
|
|
4004
|
+
}
|
|
3913
4005
|
block = this.createBlock(block, "multi", ctx);
|
|
3914
4006
|
this.insertBlock(blockExpr, block, ctx);
|
|
3915
4007
|
}
|
|
4008
|
+
wrapWithEventCatcher(expr, on) {
|
|
4009
|
+
this.helpers.add("createCatcher");
|
|
4010
|
+
let name = this.generateId("catcher");
|
|
4011
|
+
let spec = {};
|
|
4012
|
+
let handlers = [];
|
|
4013
|
+
for (let ev in on) {
|
|
4014
|
+
let handlerId = this.generateId("hdlr");
|
|
4015
|
+
let idx = handlers.push(handlerId) - 1;
|
|
4016
|
+
spec[ev] = idx;
|
|
4017
|
+
const handler = this.generateHandlerCode(ev, on[ev]);
|
|
4018
|
+
this.define(handlerId, handler);
|
|
4019
|
+
}
|
|
4020
|
+
this.staticDefs.push({ id: name, expr: `createCatcher(${JSON.stringify(spec)})` });
|
|
4021
|
+
return `${name}(${expr}, [${handlers.join(",")}])`;
|
|
4022
|
+
}
|
|
3916
4023
|
compileTSlot(ast, ctx) {
|
|
3917
4024
|
this.helpers.add("callSlot");
|
|
3918
4025
|
let { block } = ctx;
|
|
@@ -3934,13 +4041,17 @@
|
|
|
3934
4041
|
else {
|
|
3935
4042
|
if (dynamic) {
|
|
3936
4043
|
let name = this.generateId("slot");
|
|
3937
|
-
this.
|
|
4044
|
+
this.define(name, slotName);
|
|
3938
4045
|
blockString = `toggler(${name}, callSlot(ctx, node, key, ${name}), ${dynamic}, ${scope})`;
|
|
3939
4046
|
}
|
|
3940
4047
|
else {
|
|
3941
4048
|
blockString = `callSlot(ctx, node, key, ${slotName}, ${dynamic}, ${scope})`;
|
|
3942
4049
|
}
|
|
3943
4050
|
}
|
|
4051
|
+
// event handling
|
|
4052
|
+
if (ast.on) {
|
|
4053
|
+
blockString = this.wrapWithEventCatcher(blockString, ast.on);
|
|
4054
|
+
}
|
|
3944
4055
|
if (block) {
|
|
3945
4056
|
this.insertAnchor(block);
|
|
3946
4057
|
}
|
|
@@ -3961,7 +4072,7 @@
|
|
|
3961
4072
|
if (this.target.loopLevel || !this.hasSafeContext) {
|
|
3962
4073
|
ctxStr = this.generateId("ctx");
|
|
3963
4074
|
this.helpers.add("capture");
|
|
3964
|
-
this.
|
|
4075
|
+
this.define(ctxStr, `capture(ctx);`);
|
|
3965
4076
|
}
|
|
3966
4077
|
const blockString = `component(Portal, {target: ${ast.target},slots: {'default': {__render: ${name}, __ctx: ${ctxStr}}}}, key + \`${key}\`, node, ctx)`;
|
|
3967
4078
|
if (block) {
|
|
@@ -4095,8 +4206,8 @@
|
|
|
4095
4206
|
const ref = node.getAttribute("t-ref");
|
|
4096
4207
|
node.removeAttribute("t-ref");
|
|
4097
4208
|
const nodeAttrsNames = node.getAttributeNames();
|
|
4098
|
-
|
|
4099
|
-
|
|
4209
|
+
let attrs = null;
|
|
4210
|
+
let on = null;
|
|
4100
4211
|
let model = null;
|
|
4101
4212
|
for (let attr of nodeAttrsNames) {
|
|
4102
4213
|
const value = node.getAttribute(attr);
|
|
@@ -4104,6 +4215,7 @@
|
|
|
4104
4215
|
if (attr === "t-on") {
|
|
4105
4216
|
throw new Error("Missing event name with t-on directive");
|
|
4106
4217
|
}
|
|
4218
|
+
on = on || {};
|
|
4107
4219
|
on[attr.slice(5)] = value;
|
|
4108
4220
|
}
|
|
4109
4221
|
else if (attr.startsWith("t-model")) {
|
|
@@ -4141,6 +4253,7 @@
|
|
|
4141
4253
|
targetAttr: isCheckboxInput ? "checked" : "value",
|
|
4142
4254
|
specialInitTargetAttr: isRadioInput ? "checked" : null,
|
|
4143
4255
|
eventType,
|
|
4256
|
+
hasDynamicChildren: false,
|
|
4144
4257
|
shouldTrim: hasTrimMod && (isOtherInput || isTextarea),
|
|
4145
4258
|
shouldNumberize: hasNumberMod && (isOtherInput || isTextarea),
|
|
4146
4259
|
};
|
|
@@ -4161,6 +4274,7 @@
|
|
|
4161
4274
|
if (tModel && ["t-att-value", "t-attf-value"].includes(attr)) {
|
|
4162
4275
|
tModel.hasDynamicChildren = true;
|
|
4163
4276
|
}
|
|
4277
|
+
attrs = attrs || {};
|
|
4164
4278
|
attrs[attr] = value;
|
|
4165
4279
|
}
|
|
4166
4280
|
}
|
|
@@ -4311,7 +4425,7 @@
|
|
|
4311
4425
|
if (ast && ast.type === 11 /* TComponent */) {
|
|
4312
4426
|
return {
|
|
4313
4427
|
...ast,
|
|
4314
|
-
slots: { default: { content: tcall } },
|
|
4428
|
+
slots: { default: { content: tcall, scope: null, on: null, attrs: null } },
|
|
4315
4429
|
};
|
|
4316
4430
|
}
|
|
4317
4431
|
}
|
|
@@ -4395,7 +4509,6 @@
|
|
|
4395
4509
|
// -----------------------------------------------------------------------------
|
|
4396
4510
|
// Error messages when trying to use an unsupported directive on a component
|
|
4397
4511
|
const directiveErrorMap = new Map([
|
|
4398
|
-
["t-on", "t-on is no longer supported on components. Consider passing a callback in props."],
|
|
4399
4512
|
[
|
|
4400
4513
|
"t-ref",
|
|
4401
4514
|
"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 @@
|
|
|
4424
4537
|
node.removeAttribute("t-props");
|
|
4425
4538
|
const defaultSlotScope = node.getAttribute("t-slot-scope");
|
|
4426
4539
|
node.removeAttribute("t-slot-scope");
|
|
4427
|
-
|
|
4540
|
+
let on = null;
|
|
4541
|
+
let props = null;
|
|
4428
4542
|
for (let name of node.getAttributeNames()) {
|
|
4429
4543
|
const value = node.getAttribute(name);
|
|
4430
4544
|
if (name.startsWith("t-")) {
|
|
4431
|
-
|
|
4432
|
-
|
|
4545
|
+
if (name.startsWith("t-on-")) {
|
|
4546
|
+
on = on || {};
|
|
4547
|
+
on[name.slice(5)] = value;
|
|
4548
|
+
}
|
|
4549
|
+
else {
|
|
4550
|
+
const message = directiveErrorMap.get(name.split("-").slice(0, 2).join("-"));
|
|
4551
|
+
throw new Error(message || `unsupported directive on Component: ${name}`);
|
|
4552
|
+
}
|
|
4433
4553
|
}
|
|
4434
4554
|
else {
|
|
4555
|
+
props = props || {};
|
|
4435
4556
|
props[name] = value;
|
|
4436
4557
|
}
|
|
4437
4558
|
}
|
|
4438
|
-
|
|
4559
|
+
let slots = null;
|
|
4439
4560
|
if (node.hasChildNodes()) {
|
|
4440
4561
|
const clone = node.cloneNode(true);
|
|
4441
4562
|
// named slots
|
|
@@ -4463,32 +4584,36 @@
|
|
|
4463
4584
|
slotNode.remove();
|
|
4464
4585
|
const slotAst = parseNode(slotNode, ctx);
|
|
4465
4586
|
if (slotAst) {
|
|
4466
|
-
|
|
4467
|
-
|
|
4587
|
+
let on = null;
|
|
4588
|
+
let attrs = null;
|
|
4589
|
+
let scope = null;
|
|
4468
4590
|
for (let attributeName of slotNode.getAttributeNames()) {
|
|
4469
4591
|
const value = slotNode.getAttribute(attributeName);
|
|
4470
4592
|
if (attributeName === "t-slot-scope") {
|
|
4471
|
-
|
|
4593
|
+
scope = value;
|
|
4472
4594
|
continue;
|
|
4473
4595
|
}
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4596
|
+
else if (attributeName.startsWith("t-on-")) {
|
|
4597
|
+
on = on || {};
|
|
4598
|
+
on[attributeName.slice(5)] = value;
|
|
4599
|
+
}
|
|
4600
|
+
else {
|
|
4601
|
+
attrs = attrs || {};
|
|
4602
|
+
attrs[attributeName] = value;
|
|
4603
|
+
}
|
|
4478
4604
|
}
|
|
4479
|
-
slots
|
|
4605
|
+
slots = slots || {};
|
|
4606
|
+
slots[name] = { content: slotAst, on, attrs, scope };
|
|
4480
4607
|
}
|
|
4481
4608
|
}
|
|
4482
4609
|
// default slot
|
|
4483
4610
|
const defaultContent = parseChildNodes(clone, ctx);
|
|
4484
4611
|
if (defaultContent) {
|
|
4485
|
-
slots
|
|
4486
|
-
|
|
4487
|
-
slots.default.scope = defaultSlotScope;
|
|
4488
|
-
}
|
|
4612
|
+
slots = slots || {};
|
|
4613
|
+
slots.default = { content: defaultContent, on, attrs: null, scope: defaultSlotScope };
|
|
4489
4614
|
}
|
|
4490
4615
|
}
|
|
4491
|
-
return { type: 11 /* TComponent */, name, isDynamic, dynamicProps, props, slots };
|
|
4616
|
+
return { type: 11 /* TComponent */, name, isDynamic, dynamicProps, props, slots, on };
|
|
4492
4617
|
}
|
|
4493
4618
|
// -----------------------------------------------------------------------------
|
|
4494
4619
|
// Slots
|
|
@@ -4499,15 +4624,24 @@
|
|
|
4499
4624
|
}
|
|
4500
4625
|
const name = node.getAttribute("t-slot");
|
|
4501
4626
|
node.removeAttribute("t-slot");
|
|
4502
|
-
|
|
4627
|
+
let attrs = null;
|
|
4628
|
+
let on = null;
|
|
4503
4629
|
for (let attributeName of node.getAttributeNames()) {
|
|
4504
4630
|
const value = node.getAttribute(attributeName);
|
|
4505
|
-
|
|
4631
|
+
if (attributeName.startsWith("t-on-")) {
|
|
4632
|
+
on = on || {};
|
|
4633
|
+
on[attributeName.slice(5)] = value;
|
|
4634
|
+
}
|
|
4635
|
+
else {
|
|
4636
|
+
attrs = attrs || {};
|
|
4637
|
+
attrs[attributeName] = value;
|
|
4638
|
+
}
|
|
4506
4639
|
}
|
|
4507
4640
|
return {
|
|
4508
4641
|
type: 14 /* TSlot */,
|
|
4509
4642
|
name,
|
|
4510
4643
|
attrs,
|
|
4644
|
+
on,
|
|
4511
4645
|
defaultContent: parseChildNodes(node, ctx),
|
|
4512
4646
|
};
|
|
4513
4647
|
}
|
|
@@ -4767,20 +4901,22 @@
|
|
|
4767
4901
|
const node = getCurrent();
|
|
4768
4902
|
const renderFn = node.renderFn;
|
|
4769
4903
|
const decorate = node.app.dev ? wrapError : (fn) => fn;
|
|
4770
|
-
|
|
4771
|
-
|
|
4904
|
+
fn = decorate(fn.bind(node.component), "onWillRender");
|
|
4905
|
+
node.renderFn = () => {
|
|
4906
|
+
fn();
|
|
4772
4907
|
return renderFn();
|
|
4773
|
-
}
|
|
4908
|
+
};
|
|
4774
4909
|
}
|
|
4775
4910
|
function onRendered(fn) {
|
|
4776
4911
|
const node = getCurrent();
|
|
4777
4912
|
const renderFn = node.renderFn;
|
|
4778
4913
|
const decorate = node.app.dev ? wrapError : (fn) => fn;
|
|
4779
|
-
|
|
4914
|
+
fn = decorate(fn.bind(node.component), "onRendered");
|
|
4915
|
+
node.renderFn = () => {
|
|
4780
4916
|
const result = renderFn();
|
|
4781
|
-
fn
|
|
4917
|
+
fn();
|
|
4782
4918
|
return result;
|
|
4783
|
-
}
|
|
4919
|
+
};
|
|
4784
4920
|
}
|
|
4785
4921
|
function onError(callback) {
|
|
4786
4922
|
const node = getCurrent();
|
|
@@ -4882,7 +5018,7 @@
|
|
|
4882
5018
|
const { __render, __ctx, __scope } = slots[name] || {};
|
|
4883
5019
|
const slotScope = Object.create(__ctx || {});
|
|
4884
5020
|
if (__scope) {
|
|
4885
|
-
slotScope[__scope] = extra
|
|
5021
|
+
slotScope[__scope] = extra;
|
|
4886
5022
|
}
|
|
4887
5023
|
const slotBDom = __render ? __render.call(__ctx.__owl__.component, slotScope, parent, key) : null;
|
|
4888
5024
|
if (defaultContent) {
|
|
@@ -5038,6 +5174,7 @@
|
|
|
5038
5174
|
LazyValue,
|
|
5039
5175
|
safeOutput,
|
|
5040
5176
|
bind,
|
|
5177
|
+
createCatcher,
|
|
5041
5178
|
};
|
|
5042
5179
|
|
|
5043
5180
|
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
|
|
|
5390
5527
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5391
5528
|
|
|
5392
5529
|
|
|
5393
|
-
__info__.version = '2.0.0-beta.
|
|
5394
|
-
__info__.date = '2022-03-
|
|
5395
|
-
__info__.hash = '
|
|
5530
|
+
__info__.version = '2.0.0-beta.3';
|
|
5531
|
+
__info__.date = '2022-03-08T11:47:49.105Z';
|
|
5532
|
+
__info__.hash = 'c356351';
|
|
5396
5533
|
__info__.url = 'https://github.com/odoo/owl';
|
|
5397
5534
|
|
|
5398
5535
|
|