@odoo/owl 2.0.0-beta-8 → 2.0.0-beta-9

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/dist/owl.cjs.js CHANGED
@@ -1291,29 +1291,35 @@ function html(str) {
1291
1291
  }
1292
1292
 
1293
1293
  function createCatcher(eventsSpec) {
1294
- let setupFns = [];
1295
- let removeFns = [];
1296
- for (let name in eventsSpec) {
1297
- let index = eventsSpec[name];
1298
- let { setup, remove } = createEventHandler(name);
1299
- setupFns[index] = setup;
1300
- removeFns[index] = remove;
1301
- }
1302
- let n = setupFns.length;
1294
+ const n = Object.keys(eventsSpec).length;
1303
1295
  class VCatcher {
1304
1296
  constructor(child, handlers) {
1297
+ this.handlerFns = [];
1305
1298
  this.afterNode = null;
1306
1299
  this.child = child;
1307
- this.handlers = handlers;
1300
+ this.handlerData = handlers;
1308
1301
  }
1309
1302
  mount(parent, afterNode) {
1310
1303
  this.parentEl = parent;
1311
- this.afterNode = afterNode;
1312
1304
  this.child.mount(parent, afterNode);
1305
+ this.afterNode = document.createTextNode("");
1306
+ parent.insertBefore(this.afterNode, afterNode);
1307
+ this.wrapHandlerData();
1308
+ for (let name in eventsSpec) {
1309
+ const index = eventsSpec[name];
1310
+ const handler = createEventHandler(name);
1311
+ this.handlerFns[index] = handler;
1312
+ handler.setup.call(parent, this.handlerData[index]);
1313
+ }
1314
+ }
1315
+ wrapHandlerData() {
1313
1316
  for (let i = 0; i < n; i++) {
1314
- let origFn = this.handlers[i][0];
1317
+ let handler = this.handlerData[i];
1318
+ // handler = [...mods, fn, comp], so we need to replace second to last elem
1319
+ let idx = handler.length - 2;
1320
+ let origFn = handler[idx];
1315
1321
  const self = this;
1316
- this.handlers[i][0] = function (ev) {
1322
+ handler[idx] = function (ev) {
1317
1323
  const target = ev.target;
1318
1324
  let currentNode = self.child.firstNode();
1319
1325
  const afterNode = self.afterNode;
@@ -1324,18 +1330,21 @@ function createCatcher(eventsSpec) {
1324
1330
  currentNode = currentNode.nextSibling;
1325
1331
  }
1326
1332
  };
1327
- setupFns[i].call(parent, this.handlers[i]);
1328
1333
  }
1329
1334
  }
1330
1335
  moveBefore(other, afterNode) {
1331
- this.afterNode = null;
1332
1336
  this.child.moveBefore(other ? other.child : null, afterNode);
1337
+ this.parentEl.insertBefore(this.afterNode, afterNode);
1333
1338
  }
1334
1339
  patch(other, withBeforeRemove) {
1335
1340
  if (this === other) {
1336
1341
  return;
1337
1342
  }
1338
- this.handlers = other.handlers;
1343
+ this.handlerData = other.handlerData;
1344
+ this.wrapHandlerData();
1345
+ for (let i = 0; i < n; i++) {
1346
+ this.handlerFns[i].update.call(this.parentEl, this.handlerData[i]);
1347
+ }
1339
1348
  this.child.patch(other.child, withBeforeRemove);
1340
1349
  }
1341
1350
  beforeRemove() {
@@ -1343,9 +1352,10 @@ function createCatcher(eventsSpec) {
1343
1352
  }
1344
1353
  remove() {
1345
1354
  for (let i = 0; i < n; i++) {
1346
- removeFns[i].call(this.parentEl);
1355
+ this.handlerFns[i].remove.call(this.parentEl);
1347
1356
  }
1348
1357
  this.child.remove();
1358
+ this.afterNode.remove();
1349
1359
  }
1350
1360
  firstNode() {
1351
1361
  return this.child.firstNode();
@@ -2178,15 +2188,15 @@ function useComponent() {
2178
2188
  }
2179
2189
  /**
2180
2190
  * Apply default props (only top level).
2181
- *
2182
- * Note that this method does modify in place the props
2183
2191
  */
2184
2192
  function applyDefaultProps(props, defaultProps) {
2193
+ const result = Object.assign({}, props);
2185
2194
  for (let propName in defaultProps) {
2186
2195
  if (props[propName] === undefined) {
2187
- props[propName] = defaultProps[propName];
2196
+ result[propName] = defaultProps[propName];
2188
2197
  }
2189
2198
  }
2199
+ return result;
2190
2200
  }
2191
2201
  // -----------------------------------------------------------------------------
2192
2202
  // Integration with reactivity system (useState)
@@ -2239,7 +2249,7 @@ function component(name, props, key, ctx, parent) {
2239
2249
  node.forceNextRender = false;
2240
2250
  }
2241
2251
  else {
2242
- const currentProps = node.component.props;
2252
+ const currentProps = node.props;
2243
2253
  shouldRender = parentFiber.deep || arePropsDifferent(currentProps, props);
2244
2254
  }
2245
2255
  if (shouldRender) {
@@ -2286,11 +2296,12 @@ class ComponentNode {
2286
2296
  currentNode = this;
2287
2297
  this.app = app;
2288
2298
  this.parent = parent;
2299
+ this.props = props;
2289
2300
  this.parentKey = parentKey;
2290
2301
  this.level = parent ? parent.level + 1 : 0;
2291
2302
  const defaultProps = C.defaultProps;
2292
2303
  if (defaultProps) {
2293
- applyDefaultProps(props, defaultProps);
2304
+ props = applyDefaultProps(props, defaultProps);
2294
2305
  }
2295
2306
  const env = (parent && parent.childEnv) || app.env;
2296
2307
  this.childEnv = env;
@@ -2401,13 +2412,14 @@ class ComponentNode {
2401
2412
  this.status = 2 /* DESTROYED */;
2402
2413
  }
2403
2414
  async updateAndRender(props, parentFiber) {
2415
+ const rawProps = props;
2404
2416
  // update
2405
2417
  const fiber = makeChildFiber(this, parentFiber);
2406
2418
  this.fiber = fiber;
2407
2419
  const component = this.component;
2408
2420
  const defaultProps = component.constructor.defaultProps;
2409
2421
  if (defaultProps) {
2410
- applyDefaultProps(props, defaultProps);
2422
+ props = applyDefaultProps(props, defaultProps);
2411
2423
  }
2412
2424
  currentNode = this;
2413
2425
  for (const key in props) {
@@ -2423,6 +2435,7 @@ class ComponentNode {
2423
2435
  return;
2424
2436
  }
2425
2437
  component.props = props;
2438
+ this.props = rawProps;
2426
2439
  fiber.render();
2427
2440
  const parentRoot = parentFiber.root;
2428
2441
  if (this.willPatch.length) {
@@ -2925,22 +2938,33 @@ function safeOutput(value) {
2925
2938
  }
2926
2939
  let safeKey;
2927
2940
  let block;
2928
- if (value instanceof Markup) {
2929
- safeKey = `string_safe`;
2930
- block = html(value);
2931
- }
2932
- else if (value instanceof LazyValue) {
2933
- safeKey = `lazy_value`;
2934
- block = value.evaluate();
2935
- }
2936
- else if (value instanceof String || typeof value === "string") {
2937
- safeKey = "string_unsafe";
2938
- block = text(value);
2939
- }
2940
- else {
2941
- // Assuming it is a block
2942
- safeKey = "block_safe";
2943
- block = value;
2941
+ switch (typeof value) {
2942
+ case "object":
2943
+ if (value instanceof Markup) {
2944
+ safeKey = `string_safe`;
2945
+ block = html(value);
2946
+ }
2947
+ else if (value instanceof LazyValue) {
2948
+ safeKey = `lazy_value`;
2949
+ block = value.evaluate();
2950
+ }
2951
+ else if (value instanceof String) {
2952
+ safeKey = "string_unsafe";
2953
+ block = text(value);
2954
+ }
2955
+ else {
2956
+ // Assuming it is a block
2957
+ safeKey = "block_safe";
2958
+ block = value;
2959
+ }
2960
+ break;
2961
+ case "string":
2962
+ safeKey = "string_unsafe";
2963
+ block = text(value);
2964
+ break;
2965
+ default:
2966
+ safeKey = "string_unsafe";
2967
+ block = text(String(value));
2944
2968
  }
2945
2969
  return toggler(safeKey, block);
2946
2970
  }
@@ -3442,15 +3466,17 @@ function compileExpr(expr) {
3442
3466
  .map((t) => paddedValues.get(t.value) || t.value)
3443
3467
  .join("");
3444
3468
  }
3445
- const INTERP_REGEXP = /\{\{.*?\}\}/g;
3446
- const INTERP_GROUP_REGEXP = /\{\{.*?\}\}/g;
3447
- function interpolate(s) {
3469
+ const INTERP_REGEXP = /\{\{.*?\}\}|\#\{.*?\}/g;
3470
+ function replaceDynamicParts(s, replacer) {
3448
3471
  let matches = s.match(INTERP_REGEXP);
3449
3472
  if (matches && matches[0].length === s.length) {
3450
- return `(${compileExpr(s.slice(2, -2))})`;
3473
+ return `(${replacer(s.slice(2, matches[0][0] === "{" ? -2 : -1))})`;
3451
3474
  }
3452
- let r = s.replace(INTERP_GROUP_REGEXP, (s) => "${" + compileExpr(s.slice(2, -2)) + "}");
3475
+ let r = s.replace(INTERP_REGEXP, (s) => "${" + replacer(s.slice(2, s[0] === "{" ? -2 : -1)) + "}");
3453
3476
  return "`" + r + "`";
3477
+ }
3478
+ function interpolate(s) {
3479
+ return replaceDynamicParts(s, compileExpr);
3454
3480
  }
3455
3481
 
3456
3482
  // using a non-html document so that <inner/outer>HTML serializes as XML instead
@@ -3950,8 +3976,8 @@ class CodeGenerator {
3950
3976
  this.target.hasRef = true;
3951
3977
  const isDynamic = INTERP_REGEXP.test(ast.ref);
3952
3978
  if (isDynamic) {
3953
- const str = ast.ref.replace(INTERP_REGEXP, (expr) => "${" + this.captureExpression(expr.slice(2, -2), true) + "}");
3954
- const idx = block.insertData(`(el) => refs[\`${str}\`] = el`, "ref");
3979
+ const str = replaceDynamicParts(ast.ref, (expr) => this.captureExpression(expr, true));
3980
+ const idx = block.insertData(`(el) => refs[${str}] = el`, "ref");
3955
3981
  attrs["block-ref"] = String(idx);
3956
3982
  }
3957
3983
  else {
@@ -4401,21 +4427,20 @@ class CodeGenerator {
4401
4427
  return `${name}: ${value || undefined}`;
4402
4428
  }
4403
4429
  formatPropObject(obj) {
4404
- const params = [];
4405
- for (const [n, v] of Object.entries(obj)) {
4406
- params.push(this.formatProp(n, v));
4430
+ return Object.entries(obj).map(([k, v]) => this.formatProp(k, v));
4431
+ }
4432
+ getPropString(props, dynProps) {
4433
+ let propString = `{${props.join(",")}}`;
4434
+ if (dynProps) {
4435
+ propString = `Object.assign({}, ${compileExpr(dynProps)}${props.length ? ", " + propString : ""})`;
4407
4436
  }
4408
- return params.join(", ");
4437
+ return propString;
4409
4438
  }
4410
4439
  compileComponent(ast, ctx) {
4411
4440
  let { block } = ctx;
4412
4441
  // props
4413
4442
  const hasSlotsProp = "slots" in (ast.props || {});
4414
- const props = [];
4415
- const propExpr = this.formatPropObject(ast.props || {});
4416
- if (propExpr) {
4417
- props.push(propExpr);
4418
- }
4443
+ const props = ast.props ? this.formatPropObject(ast.props) : [];
4419
4444
  // slots
4420
4445
  let slotDef = "";
4421
4446
  if (ast.slots) {
@@ -4438,7 +4463,7 @@ class CodeGenerator {
4438
4463
  params.push(`__scope: "${scope}"`);
4439
4464
  }
4440
4465
  if (ast.slots[slotName].attrs) {
4441
- params.push(this.formatPropObject(ast.slots[slotName].attrs));
4466
+ params.push(...this.formatPropObject(ast.slots[slotName].attrs));
4442
4467
  }
4443
4468
  const slotInfo = `{${params.join(", ")}}`;
4444
4469
  slotStr.push(`'${slotName}': ${slotInfo}`);
@@ -4449,11 +4474,7 @@ class CodeGenerator {
4449
4474
  this.helpers.add("markRaw");
4450
4475
  props.push(`slots: markRaw(${slotDef})`);
4451
4476
  }
4452
- const propStr = `{${props.join(",")}}`;
4453
- let propString = propStr;
4454
- if (ast.dynamicProps) {
4455
- propString = `Object.assign({}, ${compileExpr(ast.dynamicProps)}${props.length ? ", " + propStr : ""})`;
4456
- }
4477
+ let propString = this.getPropString(props, ast.dynamicProps);
4457
4478
  let propVar;
4458
4479
  if ((slotDef && (ast.dynamicProps || hasSlotsProp)) || this.dev) {
4459
4480
  propVar = generateId("props");
@@ -4525,7 +4546,12 @@ class CodeGenerator {
4525
4546
  else {
4526
4547
  slotName = "'" + ast.name + "'";
4527
4548
  }
4528
- const scope = ast.attrs ? `{${this.formatPropObject(ast.attrs)}}` : null;
4549
+ const dynProps = ast.attrs ? ast.attrs["t-props"] : null;
4550
+ if (ast.attrs) {
4551
+ delete ast.attrs["t-props"];
4552
+ }
4553
+ const props = ast.attrs ? this.formatPropObject(ast.attrs) : [];
4554
+ const scope = this.getPropString(props, dynProps);
4529
4555
  if (ast.defaultContent) {
4530
4556
  const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
4531
4557
  blockString = `callSlot(ctx, node, key, ${slotName}, ${dynamic}, ${scope}, ${name})`;
@@ -5692,7 +5718,7 @@ exports.whenReady = whenReady;
5692
5718
  exports.xml = xml;
5693
5719
 
5694
5720
 
5695
- __info__.version = '2.0.0-beta-8';
5696
- __info__.date = '2022-05-31T12:25:19.319Z';
5697
- __info__.hash = 'b56a9c2';
5721
+ __info__.version = '2.0.0-beta-9';
5722
+ __info__.date = '2022-06-09T12:32:25.382Z';
5723
+ __info__.hash = '83d4471';
5698
5724
  __info__.url = 'https://github.com/odoo/owl';
package/dist/owl.es.js CHANGED
@@ -1287,29 +1287,35 @@ function html(str) {
1287
1287
  }
1288
1288
 
1289
1289
  function createCatcher(eventsSpec) {
1290
- let setupFns = [];
1291
- let removeFns = [];
1292
- for (let name in eventsSpec) {
1293
- let index = eventsSpec[name];
1294
- let { setup, remove } = createEventHandler(name);
1295
- setupFns[index] = setup;
1296
- removeFns[index] = remove;
1297
- }
1298
- let n = setupFns.length;
1290
+ const n = Object.keys(eventsSpec).length;
1299
1291
  class VCatcher {
1300
1292
  constructor(child, handlers) {
1293
+ this.handlerFns = [];
1301
1294
  this.afterNode = null;
1302
1295
  this.child = child;
1303
- this.handlers = handlers;
1296
+ this.handlerData = handlers;
1304
1297
  }
1305
1298
  mount(parent, afterNode) {
1306
1299
  this.parentEl = parent;
1307
- this.afterNode = afterNode;
1308
1300
  this.child.mount(parent, afterNode);
1301
+ this.afterNode = document.createTextNode("");
1302
+ parent.insertBefore(this.afterNode, afterNode);
1303
+ this.wrapHandlerData();
1304
+ for (let name in eventsSpec) {
1305
+ const index = eventsSpec[name];
1306
+ const handler = createEventHandler(name);
1307
+ this.handlerFns[index] = handler;
1308
+ handler.setup.call(parent, this.handlerData[index]);
1309
+ }
1310
+ }
1311
+ wrapHandlerData() {
1309
1312
  for (let i = 0; i < n; i++) {
1310
- let origFn = this.handlers[i][0];
1313
+ let handler = this.handlerData[i];
1314
+ // handler = [...mods, fn, comp], so we need to replace second to last elem
1315
+ let idx = handler.length - 2;
1316
+ let origFn = handler[idx];
1311
1317
  const self = this;
1312
- this.handlers[i][0] = function (ev) {
1318
+ handler[idx] = function (ev) {
1313
1319
  const target = ev.target;
1314
1320
  let currentNode = self.child.firstNode();
1315
1321
  const afterNode = self.afterNode;
@@ -1320,18 +1326,21 @@ function createCatcher(eventsSpec) {
1320
1326
  currentNode = currentNode.nextSibling;
1321
1327
  }
1322
1328
  };
1323
- setupFns[i].call(parent, this.handlers[i]);
1324
1329
  }
1325
1330
  }
1326
1331
  moveBefore(other, afterNode) {
1327
- this.afterNode = null;
1328
1332
  this.child.moveBefore(other ? other.child : null, afterNode);
1333
+ this.parentEl.insertBefore(this.afterNode, afterNode);
1329
1334
  }
1330
1335
  patch(other, withBeforeRemove) {
1331
1336
  if (this === other) {
1332
1337
  return;
1333
1338
  }
1334
- this.handlers = other.handlers;
1339
+ this.handlerData = other.handlerData;
1340
+ this.wrapHandlerData();
1341
+ for (let i = 0; i < n; i++) {
1342
+ this.handlerFns[i].update.call(this.parentEl, this.handlerData[i]);
1343
+ }
1335
1344
  this.child.patch(other.child, withBeforeRemove);
1336
1345
  }
1337
1346
  beforeRemove() {
@@ -1339,9 +1348,10 @@ function createCatcher(eventsSpec) {
1339
1348
  }
1340
1349
  remove() {
1341
1350
  for (let i = 0; i < n; i++) {
1342
- removeFns[i].call(this.parentEl);
1351
+ this.handlerFns[i].remove.call(this.parentEl);
1343
1352
  }
1344
1353
  this.child.remove();
1354
+ this.afterNode.remove();
1345
1355
  }
1346
1356
  firstNode() {
1347
1357
  return this.child.firstNode();
@@ -2174,15 +2184,15 @@ function useComponent() {
2174
2184
  }
2175
2185
  /**
2176
2186
  * Apply default props (only top level).
2177
- *
2178
- * Note that this method does modify in place the props
2179
2187
  */
2180
2188
  function applyDefaultProps(props, defaultProps) {
2189
+ const result = Object.assign({}, props);
2181
2190
  for (let propName in defaultProps) {
2182
2191
  if (props[propName] === undefined) {
2183
- props[propName] = defaultProps[propName];
2192
+ result[propName] = defaultProps[propName];
2184
2193
  }
2185
2194
  }
2195
+ return result;
2186
2196
  }
2187
2197
  // -----------------------------------------------------------------------------
2188
2198
  // Integration with reactivity system (useState)
@@ -2235,7 +2245,7 @@ function component(name, props, key, ctx, parent) {
2235
2245
  node.forceNextRender = false;
2236
2246
  }
2237
2247
  else {
2238
- const currentProps = node.component.props;
2248
+ const currentProps = node.props;
2239
2249
  shouldRender = parentFiber.deep || arePropsDifferent(currentProps, props);
2240
2250
  }
2241
2251
  if (shouldRender) {
@@ -2282,11 +2292,12 @@ class ComponentNode {
2282
2292
  currentNode = this;
2283
2293
  this.app = app;
2284
2294
  this.parent = parent;
2295
+ this.props = props;
2285
2296
  this.parentKey = parentKey;
2286
2297
  this.level = parent ? parent.level + 1 : 0;
2287
2298
  const defaultProps = C.defaultProps;
2288
2299
  if (defaultProps) {
2289
- applyDefaultProps(props, defaultProps);
2300
+ props = applyDefaultProps(props, defaultProps);
2290
2301
  }
2291
2302
  const env = (parent && parent.childEnv) || app.env;
2292
2303
  this.childEnv = env;
@@ -2397,13 +2408,14 @@ class ComponentNode {
2397
2408
  this.status = 2 /* DESTROYED */;
2398
2409
  }
2399
2410
  async updateAndRender(props, parentFiber) {
2411
+ const rawProps = props;
2400
2412
  // update
2401
2413
  const fiber = makeChildFiber(this, parentFiber);
2402
2414
  this.fiber = fiber;
2403
2415
  const component = this.component;
2404
2416
  const defaultProps = component.constructor.defaultProps;
2405
2417
  if (defaultProps) {
2406
- applyDefaultProps(props, defaultProps);
2418
+ props = applyDefaultProps(props, defaultProps);
2407
2419
  }
2408
2420
  currentNode = this;
2409
2421
  for (const key in props) {
@@ -2419,6 +2431,7 @@ class ComponentNode {
2419
2431
  return;
2420
2432
  }
2421
2433
  component.props = props;
2434
+ this.props = rawProps;
2422
2435
  fiber.render();
2423
2436
  const parentRoot = parentFiber.root;
2424
2437
  if (this.willPatch.length) {
@@ -2921,22 +2934,33 @@ function safeOutput(value) {
2921
2934
  }
2922
2935
  let safeKey;
2923
2936
  let block;
2924
- if (value instanceof Markup) {
2925
- safeKey = `string_safe`;
2926
- block = html(value);
2927
- }
2928
- else if (value instanceof LazyValue) {
2929
- safeKey = `lazy_value`;
2930
- block = value.evaluate();
2931
- }
2932
- else if (value instanceof String || typeof value === "string") {
2933
- safeKey = "string_unsafe";
2934
- block = text(value);
2935
- }
2936
- else {
2937
- // Assuming it is a block
2938
- safeKey = "block_safe";
2939
- block = value;
2937
+ switch (typeof value) {
2938
+ case "object":
2939
+ if (value instanceof Markup) {
2940
+ safeKey = `string_safe`;
2941
+ block = html(value);
2942
+ }
2943
+ else if (value instanceof LazyValue) {
2944
+ safeKey = `lazy_value`;
2945
+ block = value.evaluate();
2946
+ }
2947
+ else if (value instanceof String) {
2948
+ safeKey = "string_unsafe";
2949
+ block = text(value);
2950
+ }
2951
+ else {
2952
+ // Assuming it is a block
2953
+ safeKey = "block_safe";
2954
+ block = value;
2955
+ }
2956
+ break;
2957
+ case "string":
2958
+ safeKey = "string_unsafe";
2959
+ block = text(value);
2960
+ break;
2961
+ default:
2962
+ safeKey = "string_unsafe";
2963
+ block = text(String(value));
2940
2964
  }
2941
2965
  return toggler(safeKey, block);
2942
2966
  }
@@ -3438,15 +3462,17 @@ function compileExpr(expr) {
3438
3462
  .map((t) => paddedValues.get(t.value) || t.value)
3439
3463
  .join("");
3440
3464
  }
3441
- const INTERP_REGEXP = /\{\{.*?\}\}/g;
3442
- const INTERP_GROUP_REGEXP = /\{\{.*?\}\}/g;
3443
- function interpolate(s) {
3465
+ const INTERP_REGEXP = /\{\{.*?\}\}|\#\{.*?\}/g;
3466
+ function replaceDynamicParts(s, replacer) {
3444
3467
  let matches = s.match(INTERP_REGEXP);
3445
3468
  if (matches && matches[0].length === s.length) {
3446
- return `(${compileExpr(s.slice(2, -2))})`;
3469
+ return `(${replacer(s.slice(2, matches[0][0] === "{" ? -2 : -1))})`;
3447
3470
  }
3448
- let r = s.replace(INTERP_GROUP_REGEXP, (s) => "${" + compileExpr(s.slice(2, -2)) + "}");
3471
+ let r = s.replace(INTERP_REGEXP, (s) => "${" + replacer(s.slice(2, s[0] === "{" ? -2 : -1)) + "}");
3449
3472
  return "`" + r + "`";
3473
+ }
3474
+ function interpolate(s) {
3475
+ return replaceDynamicParts(s, compileExpr);
3450
3476
  }
3451
3477
 
3452
3478
  // using a non-html document so that <inner/outer>HTML serializes as XML instead
@@ -3946,8 +3972,8 @@ class CodeGenerator {
3946
3972
  this.target.hasRef = true;
3947
3973
  const isDynamic = INTERP_REGEXP.test(ast.ref);
3948
3974
  if (isDynamic) {
3949
- const str = ast.ref.replace(INTERP_REGEXP, (expr) => "${" + this.captureExpression(expr.slice(2, -2), true) + "}");
3950
- const idx = block.insertData(`(el) => refs[\`${str}\`] = el`, "ref");
3975
+ const str = replaceDynamicParts(ast.ref, (expr) => this.captureExpression(expr, true));
3976
+ const idx = block.insertData(`(el) => refs[${str}] = el`, "ref");
3951
3977
  attrs["block-ref"] = String(idx);
3952
3978
  }
3953
3979
  else {
@@ -4397,21 +4423,20 @@ class CodeGenerator {
4397
4423
  return `${name}: ${value || undefined}`;
4398
4424
  }
4399
4425
  formatPropObject(obj) {
4400
- const params = [];
4401
- for (const [n, v] of Object.entries(obj)) {
4402
- params.push(this.formatProp(n, v));
4426
+ return Object.entries(obj).map(([k, v]) => this.formatProp(k, v));
4427
+ }
4428
+ getPropString(props, dynProps) {
4429
+ let propString = `{${props.join(",")}}`;
4430
+ if (dynProps) {
4431
+ propString = `Object.assign({}, ${compileExpr(dynProps)}${props.length ? ", " + propString : ""})`;
4403
4432
  }
4404
- return params.join(", ");
4433
+ return propString;
4405
4434
  }
4406
4435
  compileComponent(ast, ctx) {
4407
4436
  let { block } = ctx;
4408
4437
  // props
4409
4438
  const hasSlotsProp = "slots" in (ast.props || {});
4410
- const props = [];
4411
- const propExpr = this.formatPropObject(ast.props || {});
4412
- if (propExpr) {
4413
- props.push(propExpr);
4414
- }
4439
+ const props = ast.props ? this.formatPropObject(ast.props) : [];
4415
4440
  // slots
4416
4441
  let slotDef = "";
4417
4442
  if (ast.slots) {
@@ -4434,7 +4459,7 @@ class CodeGenerator {
4434
4459
  params.push(`__scope: "${scope}"`);
4435
4460
  }
4436
4461
  if (ast.slots[slotName].attrs) {
4437
- params.push(this.formatPropObject(ast.slots[slotName].attrs));
4462
+ params.push(...this.formatPropObject(ast.slots[slotName].attrs));
4438
4463
  }
4439
4464
  const slotInfo = `{${params.join(", ")}}`;
4440
4465
  slotStr.push(`'${slotName}': ${slotInfo}`);
@@ -4445,11 +4470,7 @@ class CodeGenerator {
4445
4470
  this.helpers.add("markRaw");
4446
4471
  props.push(`slots: markRaw(${slotDef})`);
4447
4472
  }
4448
- const propStr = `{${props.join(",")}}`;
4449
- let propString = propStr;
4450
- if (ast.dynamicProps) {
4451
- propString = `Object.assign({}, ${compileExpr(ast.dynamicProps)}${props.length ? ", " + propStr : ""})`;
4452
- }
4473
+ let propString = this.getPropString(props, ast.dynamicProps);
4453
4474
  let propVar;
4454
4475
  if ((slotDef && (ast.dynamicProps || hasSlotsProp)) || this.dev) {
4455
4476
  propVar = generateId("props");
@@ -4521,7 +4542,12 @@ class CodeGenerator {
4521
4542
  else {
4522
4543
  slotName = "'" + ast.name + "'";
4523
4544
  }
4524
- const scope = ast.attrs ? `{${this.formatPropObject(ast.attrs)}}` : null;
4545
+ const dynProps = ast.attrs ? ast.attrs["t-props"] : null;
4546
+ if (ast.attrs) {
4547
+ delete ast.attrs["t-props"];
4548
+ }
4549
+ const props = ast.attrs ? this.formatPropObject(ast.attrs) : [];
4550
+ const scope = this.getPropString(props, dynProps);
4525
4551
  if (ast.defaultContent) {
4526
4552
  const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
4527
4553
  blockString = `callSlot(ctx, node, key, ${slotName}, ${dynamic}, ${scope}, ${name})`;
@@ -5656,7 +5682,7 @@ TemplateSet.prototype._compileTemplate = function _compileTemplate(name, templat
5656
5682
  export { App, Component, EventBus, __info__, blockDom, loadFile, markRaw, markup, mount, onError, onMounted, onPatched, onRendered, onWillDestroy, onWillPatch, onWillRender, onWillStart, onWillUnmount, onWillUpdateProps, reactive, status, toRaw, useChildSubEnv, useComponent, useEffect, useEnv, useExternalListener, useRef, useState, useSubEnv, validate, whenReady, xml };
5657
5683
 
5658
5684
 
5659
- __info__.version = '2.0.0-beta-8';
5660
- __info__.date = '2022-05-31T12:25:19.319Z';
5661
- __info__.hash = 'b56a9c2';
5685
+ __info__.version = '2.0.0-beta-9';
5686
+ __info__.date = '2022-06-09T12:32:25.382Z';
5687
+ __info__.hash = '83d4471';
5662
5688
  __info__.url = 'https://github.com/odoo/owl';