@odoo/owl 2.5.1 → 2.6.0

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.iife.js CHANGED
@@ -1628,6 +1628,13 @@
1628
1628
  fibersInError.delete(current);
1629
1629
  fibersInError.delete(root);
1630
1630
  current.appliedToDom = false;
1631
+ if (current instanceof RootFiber) {
1632
+ // it is possible that this fiber is a fiber that crashed while being
1633
+ // mounted, so the mounted list is possibly corrupted. We restore it to
1634
+ // its normal initial state (which is empty list or a list with a mount
1635
+ // fiber.
1636
+ current.mounted = current instanceof MountFiber ? [current] : [];
1637
+ }
1631
1638
  }
1632
1639
  return current;
1633
1640
  }
@@ -1744,6 +1751,7 @@
1744
1751
  const node = this.node;
1745
1752
  this.locked = true;
1746
1753
  let current = undefined;
1754
+ let mountedFibers = this.mounted;
1747
1755
  try {
1748
1756
  // Step 1: calling all willPatch lifecycle hooks
1749
1757
  for (current of this.willPatch) {
@@ -1763,7 +1771,6 @@
1763
1771
  node._patch();
1764
1772
  this.locked = false;
1765
1773
  // Step 4: calling all mounted lifecycle hooks
1766
- let mountedFibers = this.mounted;
1767
1774
  while ((current = mountedFibers.pop())) {
1768
1775
  current = current;
1769
1776
  if (current.appliedToDom) {
@@ -1784,6 +1791,15 @@
1784
1791
  }
1785
1792
  }
1786
1793
  catch (e) {
1794
+ // if mountedFibers is not empty, this means that a crash occured while
1795
+ // calling the mounted hooks of some component. So, there may still be
1796
+ // some component that have been mounted, but for which the mounted hooks
1797
+ // have not been called. Here, we remove the willUnmount hooks for these
1798
+ // specific component to prevent a worse situation (willUnmount being
1799
+ // called even though mounted has not been called)
1800
+ for (let fiber of mountedFibers) {
1801
+ fiber.node.willUnmount = [];
1802
+ }
1787
1803
  this.locked = false;
1788
1804
  node.app.handleError({ fiber: current || this, error: e });
1789
1805
  }
@@ -3725,6 +3741,7 @@
3725
3741
  index: 0,
3726
3742
  forceNewBlock: true,
3727
3743
  translate: parentCtx.translate,
3744
+ translationCtx: parentCtx.translationCtx,
3728
3745
  tKeyExpr: null,
3729
3746
  nameSpace: parentCtx.nameSpace,
3730
3747
  tModelSelectedExpr: parentCtx.tModelSelectedExpr,
@@ -3827,6 +3844,7 @@
3827
3844
  forceNewBlock: false,
3828
3845
  isLast: true,
3829
3846
  translate: true,
3847
+ translationCtx: "",
3830
3848
  tKeyExpr: null,
3831
3849
  });
3832
3850
  // define blocks and utility functions
@@ -3964,9 +3982,9 @@
3964
3982
  })
3965
3983
  .join("");
3966
3984
  }
3967
- translate(str) {
3985
+ translate(str, translationCtx) {
3968
3986
  const match = translationRE.exec(str);
3969
- return match[1] + this.translateFn(match[2]) + match[3];
3987
+ return match[1] + this.translateFn(match[2], translationCtx) + match[3];
3970
3988
  }
3971
3989
  /**
3972
3990
  * @returns the newly created block name, if any
@@ -4007,7 +4025,9 @@
4007
4025
  return this.compileTSlot(ast, ctx);
4008
4026
  case 16 /* TTranslation */:
4009
4027
  return this.compileTTranslation(ast, ctx);
4010
- case 17 /* TPortal */:
4028
+ case 17 /* TTranslationContext */:
4029
+ return this.compileTTranslationContext(ast, ctx);
4030
+ case 18 /* TPortal */:
4011
4031
  return this.compileTPortal(ast, ctx);
4012
4032
  }
4013
4033
  }
@@ -4045,7 +4065,7 @@
4045
4065
  let { block, forceNewBlock } = ctx;
4046
4066
  let value = ast.value;
4047
4067
  if (value && ctx.translate !== false) {
4048
- value = this.translate(value);
4068
+ value = this.translate(value, ctx.translationCtx);
4049
4069
  }
4050
4070
  if (!ctx.inPreTag) {
4051
4071
  value = value.replace(whitespaceRE, " ");
@@ -4080,6 +4100,7 @@
4080
4100
  return `[${modifiersCode}${this.captureExpression(handler)}, ctx]`;
4081
4101
  }
4082
4102
  compileTDomNode(ast, ctx) {
4103
+ var _a;
4083
4104
  let { block, forceNewBlock } = ctx;
4084
4105
  const isNewBlock = !block || forceNewBlock || ast.dynamicTag !== null || ast.ns;
4085
4106
  let codeIdx = this.target.code.length;
@@ -4135,7 +4156,8 @@
4135
4156
  }
4136
4157
  }
4137
4158
  else if (this.translatableAttributes.includes(key)) {
4138
- attrs[key] = this.translateFn(ast.attrs[key]);
4159
+ const attrTranslationCtx = ((_a = ast.attrsTranslationCtx) === null || _a === void 0 ? void 0 : _a[key]) || ctx.translationCtx;
4160
+ attrs[key] = this.translateFn(ast.attrs[key], attrTranslationCtx);
4139
4161
  }
4140
4162
  else {
4141
4163
  expr = `"${ast.attrs[key]}"`;
@@ -4579,7 +4601,7 @@
4579
4601
  else {
4580
4602
  let value;
4581
4603
  if (ast.defaultValue) {
4582
- const defaultValue = toStringExpression(ctx.translate ? this.translate(ast.defaultValue) : ast.defaultValue);
4604
+ const defaultValue = toStringExpression(ctx.translate ? this.translate(ast.defaultValue, ctx.translationCtx) : ast.defaultValue);
4583
4605
  if (ast.value) {
4584
4606
  value = `withDefault(${expr}, ${defaultValue})`;
4585
4607
  }
@@ -4613,9 +4635,10 @@
4613
4635
  * "some-prop" "state" "'some-prop': ctx['state']"
4614
4636
  * "onClick.bind" "onClick" "onClick: bind(ctx, ctx['onClick'])"
4615
4637
  */
4616
- formatProp(name, value) {
4638
+ formatProp(name, value, attrsTranslationCtx, translationCtx) {
4617
4639
  if (name.endsWith(".translate")) {
4618
- value = toStringExpression(this.translateFn(value));
4640
+ const attrTranslationCtx = (attrsTranslationCtx === null || attrsTranslationCtx === void 0 ? void 0 : attrsTranslationCtx[name]) || translationCtx;
4641
+ value = toStringExpression(this.translateFn(value, attrTranslationCtx));
4619
4642
  }
4620
4643
  else {
4621
4644
  value = this.captureExpression(value);
@@ -4631,14 +4654,14 @@
4631
4654
  case "translate":
4632
4655
  break;
4633
4656
  default:
4634
- throw new OwlError("Invalid prop suffix");
4657
+ throw new OwlError(`Invalid prop suffix: ${suffix}`);
4635
4658
  }
4636
4659
  }
4637
4660
  name = /^[a-z_]+$/i.test(name) ? name : `'${name}'`;
4638
4661
  return `${name}: ${value || undefined}`;
4639
4662
  }
4640
- formatPropObject(obj) {
4641
- return Object.entries(obj).map(([k, v]) => this.formatProp(k, v));
4663
+ formatPropObject(obj, attrsTranslationCtx, translationCtx) {
4664
+ return Object.entries(obj).map(([k, v]) => this.formatProp(k, v, attrsTranslationCtx, translationCtx));
4642
4665
  }
4643
4666
  getPropString(props, dynProps) {
4644
4667
  let propString = `{${props.join(",")}}`;
@@ -4651,7 +4674,9 @@
4651
4674
  let { block } = ctx;
4652
4675
  // props
4653
4676
  const hasSlotsProp = "slots" in (ast.props || {});
4654
- const props = ast.props ? this.formatPropObject(ast.props) : [];
4677
+ const props = ast.props
4678
+ ? this.formatPropObject(ast.props, ast.propsTranslationCtx, ctx.translationCtx)
4679
+ : [];
4655
4680
  // slots
4656
4681
  let slotDef = "";
4657
4682
  if (ast.slots) {
@@ -4674,7 +4699,7 @@
4674
4699
  params.push(`__scope: "${scope}"`);
4675
4700
  }
4676
4701
  if (ast.slots[slotName].attrs) {
4677
- params.push(...this.formatPropObject(ast.slots[slotName].attrs));
4702
+ params.push(...this.formatPropObject(ast.slots[slotName].attrs, ast.slots[slotName].attrsTranslationCtx, ctx.translationCtx));
4678
4703
  }
4679
4704
  const slotInfo = `{${params.join(", ")}}`;
4680
4705
  slotStr.push(`'${slotName}': ${slotInfo}`);
@@ -4787,7 +4812,9 @@
4787
4812
  if (isMultiple) {
4788
4813
  key = this.generateComponentKey(key);
4789
4814
  }
4790
- const props = ast.attrs ? this.formatPropObject(ast.attrs) : [];
4815
+ const props = ast.attrs
4816
+ ? this.formatPropObject(ast.attrs, ast.attrsTranslationCtx, ctx.translationCtx)
4817
+ : [];
4791
4818
  const scope = this.getPropString(props, dynProps);
4792
4819
  if (ast.defaultContent) {
4793
4820
  const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
@@ -4820,6 +4847,12 @@
4820
4847
  }
4821
4848
  return null;
4822
4849
  }
4850
+ compileTTranslationContext(ast, ctx) {
4851
+ if (ast.content) {
4852
+ return this.compileAST(ast.content, Object.assign({}, ctx, { translationCtx: ast.translationCtx }));
4853
+ }
4854
+ return null;
4855
+ }
4823
4856
  compileTPortal(ast, ctx) {
4824
4857
  if (!this.staticDefs.find((d) => d.id === "Portal")) {
4825
4858
  this.staticDefs.push({ id: "Portal", expr: `app.Portal` });
@@ -4889,6 +4922,7 @@
4889
4922
  parseTOutNode(node, ctx) ||
4890
4923
  parseTKey(node, ctx) ||
4891
4924
  parseTTranslation(node, ctx) ||
4925
+ parseTTranslationContext(node, ctx) ||
4892
4926
  parseTSlot(node, ctx) ||
4893
4927
  parseComponent(node, ctx) ||
4894
4928
  parseDOMNode(node, ctx) ||
@@ -4997,6 +5031,7 @@
4997
5031
  node.removeAttribute("t-ref");
4998
5032
  const nodeAttrsNames = node.getAttributeNames();
4999
5033
  let attrs = null;
5034
+ let attrsTranslationCtx = null;
5000
5035
  let on = null;
5001
5036
  let model = null;
5002
5037
  for (let attr of nodeAttrsNames) {
@@ -5057,6 +5092,11 @@
5057
5092
  else if (attr === "xmlns") {
5058
5093
  ns = value;
5059
5094
  }
5095
+ else if (attr.startsWith("t-translation-context-")) {
5096
+ const attrName = attr.slice(22);
5097
+ attrsTranslationCtx = attrsTranslationCtx || {};
5098
+ attrsTranslationCtx[attrName] = value;
5099
+ }
5060
5100
  else if (attr !== "t-name") {
5061
5101
  if (attr.startsWith("t-") && !attr.startsWith("t-att")) {
5062
5102
  throw new OwlError(`Unknown QWeb directive: '${attr}'`);
@@ -5078,6 +5118,7 @@
5078
5118
  tag: tagName,
5079
5119
  dynamicTag,
5080
5120
  attrs,
5121
+ attrsTranslationCtx,
5081
5122
  on,
5082
5123
  ref,
5083
5124
  content: children,
@@ -5218,7 +5259,15 @@
5218
5259
  if (ast && ast.type === 11 /* TComponent */) {
5219
5260
  return {
5220
5261
  ...ast,
5221
- slots: { default: { content: tcall, scope: null, on: null, attrs: null } },
5262
+ slots: {
5263
+ default: {
5264
+ content: tcall,
5265
+ scope: null,
5266
+ on: null,
5267
+ attrs: null,
5268
+ attrsTranslationCtx: null,
5269
+ },
5270
+ },
5222
5271
  };
5223
5272
  }
5224
5273
  }
@@ -5333,9 +5382,15 @@
5333
5382
  node.removeAttribute("t-slot-scope");
5334
5383
  let on = null;
5335
5384
  let props = null;
5385
+ let propsTranslationCtx = null;
5336
5386
  for (let name of node.getAttributeNames()) {
5337
5387
  const value = node.getAttribute(name);
5338
- if (name.startsWith("t-")) {
5388
+ if (name.startsWith("t-translation-context-")) {
5389
+ const attrName = name.slice(22);
5390
+ propsTranslationCtx = propsTranslationCtx || {};
5391
+ propsTranslationCtx[attrName] = value;
5392
+ }
5393
+ else if (name.startsWith("t-")) {
5339
5394
  if (name.startsWith("t-on-")) {
5340
5395
  on = on || {};
5341
5396
  on[name.slice(5)] = value;
@@ -5379,6 +5434,7 @@
5379
5434
  const slotAst = parseNode(slotNode, ctx);
5380
5435
  let on = null;
5381
5436
  let attrs = null;
5437
+ let attrsTranslationCtx = null;
5382
5438
  let scope = null;
5383
5439
  for (let attributeName of slotNode.getAttributeNames()) {
5384
5440
  const value = slotNode.getAttribute(attributeName);
@@ -5386,6 +5442,11 @@
5386
5442
  scope = value;
5387
5443
  continue;
5388
5444
  }
5445
+ else if (attributeName.startsWith("t-translation-context-")) {
5446
+ const attrName = attributeName.slice(22);
5447
+ attrsTranslationCtx = attrsTranslationCtx || {};
5448
+ attrsTranslationCtx[attrName] = value;
5449
+ }
5389
5450
  else if (attributeName.startsWith("t-on-")) {
5390
5451
  on = on || {};
5391
5452
  on[attributeName.slice(5)] = value;
@@ -5396,17 +5457,32 @@
5396
5457
  }
5397
5458
  }
5398
5459
  slots = slots || {};
5399
- slots[name] = { content: slotAst, on, attrs, scope };
5460
+ slots[name] = { content: slotAst, on, attrs, attrsTranslationCtx, scope };
5400
5461
  }
5401
5462
  // default slot
5402
5463
  const defaultContent = parseChildNodes(clone, ctx);
5403
5464
  slots = slots || {};
5404
5465
  // t-set-slot="default" has priority over content
5405
5466
  if (defaultContent && !slots.default) {
5406
- slots.default = { content: defaultContent, on, attrs: null, scope: defaultSlotScope };
5467
+ slots.default = {
5468
+ content: defaultContent,
5469
+ on,
5470
+ attrs: null,
5471
+ attrsTranslationCtx: null,
5472
+ scope: defaultSlotScope,
5473
+ };
5407
5474
  }
5408
5475
  }
5409
- return { type: 11 /* TComponent */, name, isDynamic, dynamicProps, props, slots, on };
5476
+ return {
5477
+ type: 11 /* TComponent */,
5478
+ name,
5479
+ isDynamic,
5480
+ dynamicProps,
5481
+ props,
5482
+ propsTranslationCtx,
5483
+ slots,
5484
+ on,
5485
+ };
5410
5486
  }
5411
5487
  // -----------------------------------------------------------------------------
5412
5488
  // Slots
@@ -5418,6 +5494,7 @@
5418
5494
  const name = node.getAttribute("t-slot");
5419
5495
  node.removeAttribute("t-slot");
5420
5496
  let attrs = null;
5497
+ let attrsTranslationCtx = null;
5421
5498
  let on = null;
5422
5499
  for (let attributeName of node.getAttributeNames()) {
5423
5500
  const value = node.getAttribute(attributeName);
@@ -5425,6 +5502,11 @@
5425
5502
  on = on || {};
5426
5503
  on[attributeName.slice(5)] = value;
5427
5504
  }
5505
+ else if (attributeName.startsWith("t-translation-context-")) {
5506
+ const attrName = attributeName.slice(22);
5507
+ attrsTranslationCtx = attrsTranslationCtx || {};
5508
+ attrsTranslationCtx[attrName] = value;
5509
+ }
5428
5510
  else {
5429
5511
  attrs = attrs || {};
5430
5512
  attrs[attributeName] = value;
@@ -5434,10 +5516,14 @@
5434
5516
  type: 14 /* TSlot */,
5435
5517
  name,
5436
5518
  attrs,
5519
+ attrsTranslationCtx,
5437
5520
  on,
5438
5521
  defaultContent: parseChildNodes(node, ctx),
5439
5522
  };
5440
5523
  }
5524
+ // -----------------------------------------------------------------------------
5525
+ // Translation
5526
+ // -----------------------------------------------------------------------------
5441
5527
  function parseTTranslation(node, ctx) {
5442
5528
  if (node.getAttribute("t-translation") !== "off") {
5443
5529
  return null;
@@ -5449,6 +5535,21 @@
5449
5535
  };
5450
5536
  }
5451
5537
  // -----------------------------------------------------------------------------
5538
+ // Translation Context
5539
+ // -----------------------------------------------------------------------------
5540
+ function parseTTranslationContext(node, ctx) {
5541
+ const translationCtx = node.getAttribute("t-translation-context");
5542
+ if (!translationCtx) {
5543
+ return null;
5544
+ }
5545
+ node.removeAttribute("t-translation-context");
5546
+ return {
5547
+ type: 17 /* TTranslationContext */,
5548
+ content: parseNode(node, ctx),
5549
+ translationCtx,
5550
+ };
5551
+ }
5552
+ // -----------------------------------------------------------------------------
5452
5553
  // Portal
5453
5554
  // -----------------------------------------------------------------------------
5454
5555
  function parseTPortal(node, ctx) {
@@ -5465,7 +5566,7 @@
5465
5566
  };
5466
5567
  }
5467
5568
  return {
5468
- type: 17 /* TPortal */,
5569
+ type: 18 /* TPortal */,
5469
5570
  target,
5470
5571
  content,
5471
5572
  };
@@ -5607,7 +5708,7 @@
5607
5708
  }
5608
5709
 
5609
5710
  // do not modify manually. This file is generated by the release script.
5610
- const version = "2.5.1";
5711
+ const version = "2.6.0";
5611
5712
 
5612
5713
  // -----------------------------------------------------------------------------
5613
5714
  // Scheduler
@@ -6122,8 +6223,8 @@ See https://github.com/odoo/owl/blob/${hash}/doc/reference/app.md#configuration
6122
6223
  Object.defineProperty(exports, '__esModule', { value: true });
6123
6224
 
6124
6225
 
6125
- __info__.date = '2024-11-26T08:42:41.633Z';
6126
- __info__.hash = '7fc552e';
6226
+ __info__.date = '2025-01-15T10:40:24.184Z';
6227
+ __info__.hash = 'a9be149';
6127
6228
  __info__.url = 'https://github.com/odoo/owl';
6128
6229
 
6129
6230