@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.es.js CHANGED
@@ -1625,6 +1625,13 @@ function makeRootFiber(node) {
1625
1625
  fibersInError.delete(current);
1626
1626
  fibersInError.delete(root);
1627
1627
  current.appliedToDom = false;
1628
+ if (current instanceof RootFiber) {
1629
+ // it is possible that this fiber is a fiber that crashed while being
1630
+ // mounted, so the mounted list is possibly corrupted. We restore it to
1631
+ // its normal initial state (which is empty list or a list with a mount
1632
+ // fiber.
1633
+ current.mounted = current instanceof MountFiber ? [current] : [];
1634
+ }
1628
1635
  }
1629
1636
  return current;
1630
1637
  }
@@ -1741,6 +1748,7 @@ class RootFiber extends Fiber {
1741
1748
  const node = this.node;
1742
1749
  this.locked = true;
1743
1750
  let current = undefined;
1751
+ let mountedFibers = this.mounted;
1744
1752
  try {
1745
1753
  // Step 1: calling all willPatch lifecycle hooks
1746
1754
  for (current of this.willPatch) {
@@ -1760,7 +1768,6 @@ class RootFiber extends Fiber {
1760
1768
  node._patch();
1761
1769
  this.locked = false;
1762
1770
  // Step 4: calling all mounted lifecycle hooks
1763
- let mountedFibers = this.mounted;
1764
1771
  while ((current = mountedFibers.pop())) {
1765
1772
  current = current;
1766
1773
  if (current.appliedToDom) {
@@ -1781,6 +1788,15 @@ class RootFiber extends Fiber {
1781
1788
  }
1782
1789
  }
1783
1790
  catch (e) {
1791
+ // if mountedFibers is not empty, this means that a crash occured while
1792
+ // calling the mounted hooks of some component. So, there may still be
1793
+ // some component that have been mounted, but for which the mounted hooks
1794
+ // have not been called. Here, we remove the willUnmount hooks for these
1795
+ // specific component to prevent a worse situation (willUnmount being
1796
+ // called even though mounted has not been called)
1797
+ for (let fiber of mountedFibers) {
1798
+ fiber.node.willUnmount = [];
1799
+ }
1784
1800
  this.locked = false;
1785
1801
  node.app.handleError({ fiber: current || this, error: e });
1786
1802
  }
@@ -3722,6 +3738,7 @@ function createContext(parentCtx, params) {
3722
3738
  index: 0,
3723
3739
  forceNewBlock: true,
3724
3740
  translate: parentCtx.translate,
3741
+ translationCtx: parentCtx.translationCtx,
3725
3742
  tKeyExpr: null,
3726
3743
  nameSpace: parentCtx.nameSpace,
3727
3744
  tModelSelectedExpr: parentCtx.tModelSelectedExpr,
@@ -3824,6 +3841,7 @@ class CodeGenerator {
3824
3841
  forceNewBlock: false,
3825
3842
  isLast: true,
3826
3843
  translate: true,
3844
+ translationCtx: "",
3827
3845
  tKeyExpr: null,
3828
3846
  });
3829
3847
  // define blocks and utility functions
@@ -3961,9 +3979,9 @@ class CodeGenerator {
3961
3979
  })
3962
3980
  .join("");
3963
3981
  }
3964
- translate(str) {
3982
+ translate(str, translationCtx) {
3965
3983
  const match = translationRE.exec(str);
3966
- return match[1] + this.translateFn(match[2]) + match[3];
3984
+ return match[1] + this.translateFn(match[2], translationCtx) + match[3];
3967
3985
  }
3968
3986
  /**
3969
3987
  * @returns the newly created block name, if any
@@ -4004,7 +4022,9 @@ class CodeGenerator {
4004
4022
  return this.compileTSlot(ast, ctx);
4005
4023
  case 16 /* TTranslation */:
4006
4024
  return this.compileTTranslation(ast, ctx);
4007
- case 17 /* TPortal */:
4025
+ case 17 /* TTranslationContext */:
4026
+ return this.compileTTranslationContext(ast, ctx);
4027
+ case 18 /* TPortal */:
4008
4028
  return this.compileTPortal(ast, ctx);
4009
4029
  }
4010
4030
  }
@@ -4042,7 +4062,7 @@ class CodeGenerator {
4042
4062
  let { block, forceNewBlock } = ctx;
4043
4063
  let value = ast.value;
4044
4064
  if (value && ctx.translate !== false) {
4045
- value = this.translate(value);
4065
+ value = this.translate(value, ctx.translationCtx);
4046
4066
  }
4047
4067
  if (!ctx.inPreTag) {
4048
4068
  value = value.replace(whitespaceRE, " ");
@@ -4077,6 +4097,7 @@ class CodeGenerator {
4077
4097
  return `[${modifiersCode}${this.captureExpression(handler)}, ctx]`;
4078
4098
  }
4079
4099
  compileTDomNode(ast, ctx) {
4100
+ var _a;
4080
4101
  let { block, forceNewBlock } = ctx;
4081
4102
  const isNewBlock = !block || forceNewBlock || ast.dynamicTag !== null || ast.ns;
4082
4103
  let codeIdx = this.target.code.length;
@@ -4132,7 +4153,8 @@ class CodeGenerator {
4132
4153
  }
4133
4154
  }
4134
4155
  else if (this.translatableAttributes.includes(key)) {
4135
- attrs[key] = this.translateFn(ast.attrs[key]);
4156
+ const attrTranslationCtx = ((_a = ast.attrsTranslationCtx) === null || _a === void 0 ? void 0 : _a[key]) || ctx.translationCtx;
4157
+ attrs[key] = this.translateFn(ast.attrs[key], attrTranslationCtx);
4136
4158
  }
4137
4159
  else {
4138
4160
  expr = `"${ast.attrs[key]}"`;
@@ -4576,7 +4598,7 @@ class CodeGenerator {
4576
4598
  else {
4577
4599
  let value;
4578
4600
  if (ast.defaultValue) {
4579
- const defaultValue = toStringExpression(ctx.translate ? this.translate(ast.defaultValue) : ast.defaultValue);
4601
+ const defaultValue = toStringExpression(ctx.translate ? this.translate(ast.defaultValue, ctx.translationCtx) : ast.defaultValue);
4580
4602
  if (ast.value) {
4581
4603
  value = `withDefault(${expr}, ${defaultValue})`;
4582
4604
  }
@@ -4610,9 +4632,10 @@ class CodeGenerator {
4610
4632
  * "some-prop" "state" "'some-prop': ctx['state']"
4611
4633
  * "onClick.bind" "onClick" "onClick: bind(ctx, ctx['onClick'])"
4612
4634
  */
4613
- formatProp(name, value) {
4635
+ formatProp(name, value, attrsTranslationCtx, translationCtx) {
4614
4636
  if (name.endsWith(".translate")) {
4615
- value = toStringExpression(this.translateFn(value));
4637
+ const attrTranslationCtx = (attrsTranslationCtx === null || attrsTranslationCtx === void 0 ? void 0 : attrsTranslationCtx[name]) || translationCtx;
4638
+ value = toStringExpression(this.translateFn(value, attrTranslationCtx));
4616
4639
  }
4617
4640
  else {
4618
4641
  value = this.captureExpression(value);
@@ -4628,14 +4651,14 @@ class CodeGenerator {
4628
4651
  case "translate":
4629
4652
  break;
4630
4653
  default:
4631
- throw new OwlError("Invalid prop suffix");
4654
+ throw new OwlError(`Invalid prop suffix: ${suffix}`);
4632
4655
  }
4633
4656
  }
4634
4657
  name = /^[a-z_]+$/i.test(name) ? name : `'${name}'`;
4635
4658
  return `${name}: ${value || undefined}`;
4636
4659
  }
4637
- formatPropObject(obj) {
4638
- return Object.entries(obj).map(([k, v]) => this.formatProp(k, v));
4660
+ formatPropObject(obj, attrsTranslationCtx, translationCtx) {
4661
+ return Object.entries(obj).map(([k, v]) => this.formatProp(k, v, attrsTranslationCtx, translationCtx));
4639
4662
  }
4640
4663
  getPropString(props, dynProps) {
4641
4664
  let propString = `{${props.join(",")}}`;
@@ -4648,7 +4671,9 @@ class CodeGenerator {
4648
4671
  let { block } = ctx;
4649
4672
  // props
4650
4673
  const hasSlotsProp = "slots" in (ast.props || {});
4651
- const props = ast.props ? this.formatPropObject(ast.props) : [];
4674
+ const props = ast.props
4675
+ ? this.formatPropObject(ast.props, ast.propsTranslationCtx, ctx.translationCtx)
4676
+ : [];
4652
4677
  // slots
4653
4678
  let slotDef = "";
4654
4679
  if (ast.slots) {
@@ -4671,7 +4696,7 @@ class CodeGenerator {
4671
4696
  params.push(`__scope: "${scope}"`);
4672
4697
  }
4673
4698
  if (ast.slots[slotName].attrs) {
4674
- params.push(...this.formatPropObject(ast.slots[slotName].attrs));
4699
+ params.push(...this.formatPropObject(ast.slots[slotName].attrs, ast.slots[slotName].attrsTranslationCtx, ctx.translationCtx));
4675
4700
  }
4676
4701
  const slotInfo = `{${params.join(", ")}}`;
4677
4702
  slotStr.push(`'${slotName}': ${slotInfo}`);
@@ -4784,7 +4809,9 @@ class CodeGenerator {
4784
4809
  if (isMultiple) {
4785
4810
  key = this.generateComponentKey(key);
4786
4811
  }
4787
- const props = ast.attrs ? this.formatPropObject(ast.attrs) : [];
4812
+ const props = ast.attrs
4813
+ ? this.formatPropObject(ast.attrs, ast.attrsTranslationCtx, ctx.translationCtx)
4814
+ : [];
4788
4815
  const scope = this.getPropString(props, dynProps);
4789
4816
  if (ast.defaultContent) {
4790
4817
  const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
@@ -4817,6 +4844,12 @@ class CodeGenerator {
4817
4844
  }
4818
4845
  return null;
4819
4846
  }
4847
+ compileTTranslationContext(ast, ctx) {
4848
+ if (ast.content) {
4849
+ return this.compileAST(ast.content, Object.assign({}, ctx, { translationCtx: ast.translationCtx }));
4850
+ }
4851
+ return null;
4852
+ }
4820
4853
  compileTPortal(ast, ctx) {
4821
4854
  if (!this.staticDefs.find((d) => d.id === "Portal")) {
4822
4855
  this.staticDefs.push({ id: "Portal", expr: `app.Portal` });
@@ -4886,6 +4919,7 @@ function parseNode(node, ctx) {
4886
4919
  parseTOutNode(node, ctx) ||
4887
4920
  parseTKey(node, ctx) ||
4888
4921
  parseTTranslation(node, ctx) ||
4922
+ parseTTranslationContext(node, ctx) ||
4889
4923
  parseTSlot(node, ctx) ||
4890
4924
  parseComponent(node, ctx) ||
4891
4925
  parseDOMNode(node, ctx) ||
@@ -4994,6 +5028,7 @@ function parseDOMNode(node, ctx) {
4994
5028
  node.removeAttribute("t-ref");
4995
5029
  const nodeAttrsNames = node.getAttributeNames();
4996
5030
  let attrs = null;
5031
+ let attrsTranslationCtx = null;
4997
5032
  let on = null;
4998
5033
  let model = null;
4999
5034
  for (let attr of nodeAttrsNames) {
@@ -5054,6 +5089,11 @@ function parseDOMNode(node, ctx) {
5054
5089
  else if (attr === "xmlns") {
5055
5090
  ns = value;
5056
5091
  }
5092
+ else if (attr.startsWith("t-translation-context-")) {
5093
+ const attrName = attr.slice(22);
5094
+ attrsTranslationCtx = attrsTranslationCtx || {};
5095
+ attrsTranslationCtx[attrName] = value;
5096
+ }
5057
5097
  else if (attr !== "t-name") {
5058
5098
  if (attr.startsWith("t-") && !attr.startsWith("t-att")) {
5059
5099
  throw new OwlError(`Unknown QWeb directive: '${attr}'`);
@@ -5075,6 +5115,7 @@ function parseDOMNode(node, ctx) {
5075
5115
  tag: tagName,
5076
5116
  dynamicTag,
5077
5117
  attrs,
5118
+ attrsTranslationCtx,
5078
5119
  on,
5079
5120
  ref,
5080
5121
  content: children,
@@ -5215,7 +5256,15 @@ function parseTCall(node, ctx) {
5215
5256
  if (ast && ast.type === 11 /* TComponent */) {
5216
5257
  return {
5217
5258
  ...ast,
5218
- slots: { default: { content: tcall, scope: null, on: null, attrs: null } },
5259
+ slots: {
5260
+ default: {
5261
+ content: tcall,
5262
+ scope: null,
5263
+ on: null,
5264
+ attrs: null,
5265
+ attrsTranslationCtx: null,
5266
+ },
5267
+ },
5219
5268
  };
5220
5269
  }
5221
5270
  }
@@ -5330,9 +5379,15 @@ function parseComponent(node, ctx) {
5330
5379
  node.removeAttribute("t-slot-scope");
5331
5380
  let on = null;
5332
5381
  let props = null;
5382
+ let propsTranslationCtx = null;
5333
5383
  for (let name of node.getAttributeNames()) {
5334
5384
  const value = node.getAttribute(name);
5335
- if (name.startsWith("t-")) {
5385
+ if (name.startsWith("t-translation-context-")) {
5386
+ const attrName = name.slice(22);
5387
+ propsTranslationCtx = propsTranslationCtx || {};
5388
+ propsTranslationCtx[attrName] = value;
5389
+ }
5390
+ else if (name.startsWith("t-")) {
5336
5391
  if (name.startsWith("t-on-")) {
5337
5392
  on = on || {};
5338
5393
  on[name.slice(5)] = value;
@@ -5376,6 +5431,7 @@ function parseComponent(node, ctx) {
5376
5431
  const slotAst = parseNode(slotNode, ctx);
5377
5432
  let on = null;
5378
5433
  let attrs = null;
5434
+ let attrsTranslationCtx = null;
5379
5435
  let scope = null;
5380
5436
  for (let attributeName of slotNode.getAttributeNames()) {
5381
5437
  const value = slotNode.getAttribute(attributeName);
@@ -5383,6 +5439,11 @@ function parseComponent(node, ctx) {
5383
5439
  scope = value;
5384
5440
  continue;
5385
5441
  }
5442
+ else if (attributeName.startsWith("t-translation-context-")) {
5443
+ const attrName = attributeName.slice(22);
5444
+ attrsTranslationCtx = attrsTranslationCtx || {};
5445
+ attrsTranslationCtx[attrName] = value;
5446
+ }
5386
5447
  else if (attributeName.startsWith("t-on-")) {
5387
5448
  on = on || {};
5388
5449
  on[attributeName.slice(5)] = value;
@@ -5393,17 +5454,32 @@ function parseComponent(node, ctx) {
5393
5454
  }
5394
5455
  }
5395
5456
  slots = slots || {};
5396
- slots[name] = { content: slotAst, on, attrs, scope };
5457
+ slots[name] = { content: slotAst, on, attrs, attrsTranslationCtx, scope };
5397
5458
  }
5398
5459
  // default slot
5399
5460
  const defaultContent = parseChildNodes(clone, ctx);
5400
5461
  slots = slots || {};
5401
5462
  // t-set-slot="default" has priority over content
5402
5463
  if (defaultContent && !slots.default) {
5403
- slots.default = { content: defaultContent, on, attrs: null, scope: defaultSlotScope };
5464
+ slots.default = {
5465
+ content: defaultContent,
5466
+ on,
5467
+ attrs: null,
5468
+ attrsTranslationCtx: null,
5469
+ scope: defaultSlotScope,
5470
+ };
5404
5471
  }
5405
5472
  }
5406
- return { type: 11 /* TComponent */, name, isDynamic, dynamicProps, props, slots, on };
5473
+ return {
5474
+ type: 11 /* TComponent */,
5475
+ name,
5476
+ isDynamic,
5477
+ dynamicProps,
5478
+ props,
5479
+ propsTranslationCtx,
5480
+ slots,
5481
+ on,
5482
+ };
5407
5483
  }
5408
5484
  // -----------------------------------------------------------------------------
5409
5485
  // Slots
@@ -5415,6 +5491,7 @@ function parseTSlot(node, ctx) {
5415
5491
  const name = node.getAttribute("t-slot");
5416
5492
  node.removeAttribute("t-slot");
5417
5493
  let attrs = null;
5494
+ let attrsTranslationCtx = null;
5418
5495
  let on = null;
5419
5496
  for (let attributeName of node.getAttributeNames()) {
5420
5497
  const value = node.getAttribute(attributeName);
@@ -5422,6 +5499,11 @@ function parseTSlot(node, ctx) {
5422
5499
  on = on || {};
5423
5500
  on[attributeName.slice(5)] = value;
5424
5501
  }
5502
+ else if (attributeName.startsWith("t-translation-context-")) {
5503
+ const attrName = attributeName.slice(22);
5504
+ attrsTranslationCtx = attrsTranslationCtx || {};
5505
+ attrsTranslationCtx[attrName] = value;
5506
+ }
5425
5507
  else {
5426
5508
  attrs = attrs || {};
5427
5509
  attrs[attributeName] = value;
@@ -5431,10 +5513,14 @@ function parseTSlot(node, ctx) {
5431
5513
  type: 14 /* TSlot */,
5432
5514
  name,
5433
5515
  attrs,
5516
+ attrsTranslationCtx,
5434
5517
  on,
5435
5518
  defaultContent: parseChildNodes(node, ctx),
5436
5519
  };
5437
5520
  }
5521
+ // -----------------------------------------------------------------------------
5522
+ // Translation
5523
+ // -----------------------------------------------------------------------------
5438
5524
  function parseTTranslation(node, ctx) {
5439
5525
  if (node.getAttribute("t-translation") !== "off") {
5440
5526
  return null;
@@ -5446,6 +5532,21 @@ function parseTTranslation(node, ctx) {
5446
5532
  };
5447
5533
  }
5448
5534
  // -----------------------------------------------------------------------------
5535
+ // Translation Context
5536
+ // -----------------------------------------------------------------------------
5537
+ function parseTTranslationContext(node, ctx) {
5538
+ const translationCtx = node.getAttribute("t-translation-context");
5539
+ if (!translationCtx) {
5540
+ return null;
5541
+ }
5542
+ node.removeAttribute("t-translation-context");
5543
+ return {
5544
+ type: 17 /* TTranslationContext */,
5545
+ content: parseNode(node, ctx),
5546
+ translationCtx,
5547
+ };
5548
+ }
5549
+ // -----------------------------------------------------------------------------
5449
5550
  // Portal
5450
5551
  // -----------------------------------------------------------------------------
5451
5552
  function parseTPortal(node, ctx) {
@@ -5462,7 +5563,7 @@ function parseTPortal(node, ctx) {
5462
5563
  };
5463
5564
  }
5464
5565
  return {
5465
- type: 17 /* TPortal */,
5566
+ type: 18 /* TPortal */,
5466
5567
  target,
5467
5568
  content,
5468
5569
  };
@@ -5604,7 +5705,7 @@ function compile(template, options = {
5604
5705
  }
5605
5706
 
5606
5707
  // do not modify manually. This file is generated by the release script.
5607
- const version = "2.5.1";
5708
+ const version = "2.6.0";
5608
5709
 
5609
5710
  // -----------------------------------------------------------------------------
5610
5711
  // Scheduler
@@ -6082,6 +6183,6 @@ TemplateSet.prototype._compileTemplate = function _compileTemplate(name, templat
6082
6183
  export { App, Component, EventBus, OwlError, __info__, batched, 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, validateType, whenReady, xml };
6083
6184
 
6084
6185
 
6085
- __info__.date = '2024-11-26T08:42:41.633Z';
6086
- __info__.hash = '7fc552e';
6186
+ __info__.date = '2025-01-15T10:40:24.184Z';
6187
+ __info__.hash = 'a9be149';
6087
6188
  __info__.url = 'https://github.com/odoo/owl';