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