@odoo/owl 2.0.0-beta-20 → 2.0.0-beta-22

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
@@ -675,6 +675,15 @@
675
675
  : document.createElement(tagName);
676
676
  }
677
677
  if (el instanceof Element) {
678
+ if (!domParentTree) {
679
+ // some html elements may have side effects when setting their attributes.
680
+ // For example, setting the src attribute of an <img/> will trigger a
681
+ // request to get the corresponding image. This is something that we
682
+ // don't want at compile time. We avoid that by putting the content of
683
+ // the block in a <template/> element
684
+ const fragment = document.createElement("template").content;
685
+ fragment.appendChild(el);
686
+ }
678
687
  for (let i = 0; i < attrs.length; i++) {
679
688
  const attrName = attrs[i].name;
680
689
  const attrValue = attrs[i].value;
@@ -2599,67 +2608,71 @@
2599
2608
 
2600
2609
  const VText = text("").constructor;
2601
2610
  class VPortal extends VText {
2602
- constructor(selector, realBDom) {
2611
+ constructor(selector, content) {
2603
2612
  super("");
2604
2613
  this.target = null;
2605
2614
  this.selector = selector;
2606
- this.realBDom = realBDom;
2615
+ this.content = content;
2607
2616
  }
2608
2617
  mount(parent, anchor) {
2609
2618
  super.mount(parent, anchor);
2610
2619
  this.target = document.querySelector(this.selector);
2611
- if (!this.target) {
2612
- let el = this.el;
2613
- while (el && el.parentElement instanceof HTMLElement) {
2614
- el = el.parentElement;
2615
- }
2616
- this.target = el && el.querySelector(this.selector);
2617
- if (!this.target) {
2618
- throw new OwlError("invalid portal target");
2619
- }
2620
+ if (this.target) {
2621
+ this.content.mount(this.target, null);
2622
+ }
2623
+ else {
2624
+ this.content.mount(parent, anchor);
2620
2625
  }
2621
- this.realBDom.mount(this.target, null);
2622
2626
  }
2623
2627
  beforeRemove() {
2624
- this.realBDom.beforeRemove();
2628
+ this.content.beforeRemove();
2625
2629
  }
2626
2630
  remove() {
2627
- if (this.realBDom) {
2631
+ if (this.content) {
2628
2632
  super.remove();
2629
- this.realBDom.remove();
2630
- this.realBDom = null;
2633
+ this.content.remove();
2634
+ this.content = null;
2631
2635
  }
2632
2636
  }
2633
2637
  patch(other) {
2634
2638
  super.patch(other);
2635
- if (this.realBDom) {
2636
- this.realBDom.patch(other.realBDom, true);
2639
+ if (this.content) {
2640
+ this.content.patch(other.content, true);
2637
2641
  }
2638
2642
  else {
2639
- this.realBDom = other.realBDom;
2640
- this.realBDom.mount(this.target, null);
2643
+ this.content = other.content;
2644
+ this.content.mount(this.target, null);
2641
2645
  }
2642
2646
  }
2643
2647
  }
2644
2648
  /**
2645
- * <t t-slot="default"/>
2649
+ * kind of similar to <t t-slot="default"/>, but it wraps it around a VPortal
2646
2650
  */
2647
2651
  function portalTemplate(app, bdom, helpers) {
2648
2652
  let { callSlot } = helpers;
2649
2653
  return function template(ctx, node, key = "") {
2650
- return callSlot(ctx, node, key, "default", false, null);
2654
+ return new VPortal(ctx.props.target, callSlot(ctx, node, key, "default", false, null));
2651
2655
  };
2652
2656
  }
2653
2657
  class Portal extends Component {
2654
2658
  setup() {
2655
2659
  const node = this.__owl__;
2656
- const renderFn = node.renderFn;
2657
- node.renderFn = () => new VPortal(this.props.target, renderFn());
2658
- onWillUnmount(() => {
2659
- if (node.bdom) {
2660
- node.bdom.remove();
2660
+ onMounted(() => {
2661
+ const portal = node.bdom;
2662
+ if (!portal.target) {
2663
+ const target = document.querySelector(this.props.target);
2664
+ if (target) {
2665
+ portal.content.moveBefore(target, null);
2666
+ }
2667
+ else {
2668
+ throw new OwlError("invalid portal target");
2669
+ }
2661
2670
  }
2662
2671
  });
2672
+ onWillUnmount(() => {
2673
+ const portal = node.bdom;
2674
+ portal.remove();
2675
+ });
2663
2676
  }
2664
2677
  }
2665
2678
  Portal.template = "__portal__";
@@ -2893,14 +2906,15 @@
2893
2906
  return true;
2894
2907
  }
2895
2908
  class LazyValue {
2896
- constructor(fn, ctx, component, node) {
2909
+ constructor(fn, ctx, component, node, key) {
2897
2910
  this.fn = fn;
2898
2911
  this.ctx = capture(ctx);
2899
2912
  this.component = component;
2900
2913
  this.node = node;
2914
+ this.key = key;
2901
2915
  }
2902
2916
  evaluate() {
2903
- return this.fn.call(this.component, this.ctx, this.node);
2917
+ return this.fn.call(this.component, this.ctx, this.node, this.key);
2904
2918
  }
2905
2919
  toString() {
2906
2920
  return this.evaluate().toString();
@@ -2982,10 +2996,10 @@
2982
2996
  * visit recursively the props and all the children to check if they are valid.
2983
2997
  * This is why it is only done in 'dev' mode.
2984
2998
  */
2985
- function validateProps(name, props, parent) {
2999
+ function validateProps(name, props, comp) {
2986
3000
  const ComponentClass = typeof name !== "string"
2987
3001
  ? name
2988
- : parent.constructor.components[name];
3002
+ : comp.constructor.components[name];
2989
3003
  if (!ComponentClass) {
2990
3004
  // this is an error, wrong component. We silently return here instead so the
2991
3005
  // error is triggered by the usual path ('component' function)
@@ -2993,7 +3007,7 @@
2993
3007
  }
2994
3008
  const schema = ComponentClass.props;
2995
3009
  if (!schema) {
2996
- if (parent.__owl__.app.warnIfNoStaticProps) {
3010
+ if (comp.__owl__.app.warnIfNoStaticProps) {
2997
3011
  console.warn(`Component '${ComponentClass.name}' does not have a static props description`);
2998
3012
  }
2999
3013
  return;
@@ -3586,6 +3600,13 @@
3586
3600
  result.push(`}`);
3587
3601
  return result.join("\n ");
3588
3602
  }
3603
+ currentKey(ctx) {
3604
+ let key = this.loopLevel ? `key${this.loopLevel}` : "key";
3605
+ if (ctx.tKeyExpr) {
3606
+ key = `${ctx.tKeyExpr} + ${key}`;
3607
+ }
3608
+ return key;
3609
+ }
3589
3610
  }
3590
3611
  const TRANSLATABLE_ATTRS = ["label", "title", "placeholder", "alt"];
3591
3612
  const translationRE = /^(\s*)([\s\S]+?)(\s*)$/;
@@ -3715,18 +3736,14 @@
3715
3736
  }
3716
3737
  insertBlock(expression, block, ctx) {
3717
3738
  let blockExpr = block.generateExpr(expression);
3718
- const tKeyExpr = ctx.tKeyExpr;
3719
3739
  if (block.parentVar) {
3720
- let keyArg = `key${this.target.loopLevel}`;
3721
- if (tKeyExpr) {
3722
- keyArg = `${tKeyExpr} + ${keyArg}`;
3723
- }
3740
+ let key = this.target.currentKey(ctx);
3724
3741
  this.helpers.add("withKey");
3725
- this.addLine(`${block.parentVar}[${ctx.index}] = withKey(${blockExpr}, ${keyArg});`);
3742
+ this.addLine(`${block.parentVar}[${ctx.index}] = withKey(${blockExpr}, ${key});`);
3726
3743
  return;
3727
3744
  }
3728
- if (tKeyExpr) {
3729
- blockExpr = `toggler(${tKeyExpr}, ${blockExpr})`;
3745
+ if (ctx.tKeyExpr) {
3746
+ blockExpr = `toggler(${ctx.tKeyExpr}, ${blockExpr})`;
3730
3747
  }
3731
3748
  if (block.isRoot && !ctx.preventRoot) {
3732
3749
  if (this.target.on) {
@@ -3771,74 +3788,62 @@
3771
3788
  })
3772
3789
  .join("");
3773
3790
  }
3791
+ /**
3792
+ * @returns the newly created block name, if any
3793
+ */
3774
3794
  compileAST(ast, ctx) {
3775
3795
  switch (ast.type) {
3776
3796
  case 1 /* Comment */:
3777
- this.compileComment(ast, ctx);
3778
- break;
3797
+ return this.compileComment(ast, ctx);
3779
3798
  case 0 /* Text */:
3780
- this.compileText(ast, ctx);
3781
- break;
3799
+ return this.compileText(ast, ctx);
3782
3800
  case 2 /* DomNode */:
3783
- this.compileTDomNode(ast, ctx);
3784
- break;
3801
+ return this.compileTDomNode(ast, ctx);
3785
3802
  case 4 /* TEsc */:
3786
- this.compileTEsc(ast, ctx);
3787
- break;
3803
+ return this.compileTEsc(ast, ctx);
3788
3804
  case 8 /* TOut */:
3789
- this.compileTOut(ast, ctx);
3790
- break;
3805
+ return this.compileTOut(ast, ctx);
3791
3806
  case 5 /* TIf */:
3792
- this.compileTIf(ast, ctx);
3793
- break;
3807
+ return this.compileTIf(ast, ctx);
3794
3808
  case 9 /* TForEach */:
3795
- this.compileTForeach(ast, ctx);
3796
- break;
3809
+ return this.compileTForeach(ast, ctx);
3797
3810
  case 10 /* TKey */:
3798
- this.compileTKey(ast, ctx);
3799
- break;
3811
+ return this.compileTKey(ast, ctx);
3800
3812
  case 3 /* Multi */:
3801
- this.compileMulti(ast, ctx);
3802
- break;
3813
+ return this.compileMulti(ast, ctx);
3803
3814
  case 7 /* TCall */:
3804
- this.compileTCall(ast, ctx);
3805
- break;
3815
+ return this.compileTCall(ast, ctx);
3806
3816
  case 15 /* TCallBlock */:
3807
- this.compileTCallBlock(ast, ctx);
3808
- break;
3817
+ return this.compileTCallBlock(ast, ctx);
3809
3818
  case 6 /* TSet */:
3810
- this.compileTSet(ast, ctx);
3811
- break;
3819
+ return this.compileTSet(ast, ctx);
3812
3820
  case 11 /* TComponent */:
3813
- this.compileComponent(ast, ctx);
3814
- break;
3821
+ return this.compileComponent(ast, ctx);
3815
3822
  case 12 /* TDebug */:
3816
- this.compileDebug(ast, ctx);
3817
- break;
3823
+ return this.compileDebug(ast, ctx);
3818
3824
  case 13 /* TLog */:
3819
- this.compileLog(ast, ctx);
3820
- break;
3825
+ return this.compileLog(ast, ctx);
3821
3826
  case 14 /* TSlot */:
3822
- this.compileTSlot(ast, ctx);
3823
- break;
3827
+ return this.compileTSlot(ast, ctx);
3824
3828
  case 16 /* TTranslation */:
3825
- this.compileTTranslation(ast, ctx);
3826
- break;
3829
+ return this.compileTTranslation(ast, ctx);
3827
3830
  case 17 /* TPortal */:
3828
- this.compileTPortal(ast, ctx);
3831
+ return this.compileTPortal(ast, ctx);
3829
3832
  }
3830
3833
  }
3831
3834
  compileDebug(ast, ctx) {
3832
3835
  this.addLine(`debugger;`);
3833
3836
  if (ast.content) {
3834
- this.compileAST(ast.content, ctx);
3837
+ return this.compileAST(ast.content, ctx);
3835
3838
  }
3839
+ return null;
3836
3840
  }
3837
3841
  compileLog(ast, ctx) {
3838
3842
  this.addLine(`console.log(${compileExpr(ast.expr)});`);
3839
3843
  if (ast.content) {
3840
- this.compileAST(ast.content, ctx);
3844
+ return this.compileAST(ast.content, ctx);
3841
3845
  }
3846
+ return null;
3842
3847
  }
3843
3848
  compileComment(ast, ctx) {
3844
3849
  let { block, forceNewBlock } = ctx;
@@ -3854,6 +3859,7 @@
3854
3859
  const text = xmlDoc.createComment(ast.value);
3855
3860
  block.insert(text);
3856
3861
  }
3862
+ return block.varName;
3857
3863
  }
3858
3864
  compileText(ast, ctx) {
3859
3865
  let { block, forceNewBlock } = ctx;
@@ -3873,6 +3879,7 @@
3873
3879
  const createFn = ast.type === 0 /* Text */ ? xmlDoc.createTextNode : xmlDoc.createComment;
3874
3880
  block.insert(createFn.call(xmlDoc, value));
3875
3881
  }
3882
+ return block.varName;
3876
3883
  }
3877
3884
  generateHandlerCode(rawEvent, handler) {
3878
3885
  const modifiers = rawEvent
@@ -4065,6 +4072,7 @@
4065
4072
  this.addLine(`let ${block.children.map((c) => c.varName)};`, codeIdx);
4066
4073
  }
4067
4074
  }
4075
+ return block.varName;
4068
4076
  }
4069
4077
  compileTEsc(ast, ctx) {
4070
4078
  let { block, forceNewBlock } = ctx;
@@ -4089,6 +4097,7 @@
4089
4097
  const text = xmlDoc.createElement(`block-text-${idx}`);
4090
4098
  block.insert(text);
4091
4099
  }
4100
+ return block.varName;
4092
4101
  }
4093
4102
  compileTOut(ast, ctx) {
4094
4103
  let { block } = ctx;
@@ -4114,6 +4123,7 @@
4114
4123
  blockStr = `safeOutput(${compileExpr(ast.expr)})`;
4115
4124
  }
4116
4125
  this.insertBlock(blockStr, block, ctx);
4126
+ return block.varName;
4117
4127
  }
4118
4128
  compileTIfBranch(content, block, ctx) {
4119
4129
  this.target.indentLevel++;
@@ -4168,6 +4178,7 @@
4168
4178
  const args = block.children.map((c) => c.varName).join(", ");
4169
4179
  this.insertBlock(`multi([${args}])`, block, ctx);
4170
4180
  }
4181
+ return block.varName;
4171
4182
  }
4172
4183
  compileTForeach(ast, ctx) {
4173
4184
  let { block } = ctx;
@@ -4240,6 +4251,7 @@
4240
4251
  this.addLine(`ctx = ctx.__proto__;`);
4241
4252
  }
4242
4253
  this.insertBlock("l", block, ctx);
4254
+ return block.varName;
4243
4255
  }
4244
4256
  compileTKey(ast, ctx) {
4245
4257
  const tKeyExpr = generateId("tKey_");
@@ -4249,7 +4261,7 @@
4249
4261
  block: ctx.block,
4250
4262
  index: ctx.index,
4251
4263
  });
4252
- this.compileAST(ast.content, ctx);
4264
+ return this.compileAST(ast.content, ctx);
4253
4265
  }
4254
4266
  compileMulti(ast, ctx) {
4255
4267
  let { block, forceNewBlock } = ctx;
@@ -4257,11 +4269,13 @@
4257
4269
  let codeIdx = this.target.code.length;
4258
4270
  if (isNewBlock) {
4259
4271
  const n = ast.content.filter((c) => c.type !== 6 /* TSet */).length;
4272
+ let result = null;
4260
4273
  if (n <= 1) {
4261
4274
  for (let child of ast.content) {
4262
- this.compileAST(child, ctx);
4275
+ const blockName = this.compileAST(child, ctx);
4276
+ result = result || blockName;
4263
4277
  }
4264
- return;
4278
+ return result;
4265
4279
  }
4266
4280
  block = this.createBlock(block, "multi", ctx);
4267
4281
  }
@@ -4301,6 +4315,7 @@
4301
4315
  const args = block.children.map((c) => c.varName).join(", ");
4302
4316
  this.insertBlock(`multi([${args}])`, block, ctx);
4303
4317
  }
4318
+ return block.varName;
4304
4319
  }
4305
4320
  compileTCall(ast, ctx) {
4306
4321
  let { block, forceNewBlock } = ctx;
@@ -4313,12 +4328,11 @@
4313
4328
  this.addLine(`${ctxVar} = Object.create(${ctxVar});`);
4314
4329
  this.addLine(`${ctxVar}[isBoundary] = 1;`);
4315
4330
  this.helpers.add("isBoundary");
4316
- const nextId = BlockDescription.nextBlockId;
4317
4331
  const subCtx = createContext(ctx, { preventRoot: true, ctxVar });
4318
- this.compileAST({ type: 3 /* Multi */, content: ast.body }, subCtx);
4319
- if (nextId !== BlockDescription.nextBlockId) {
4332
+ const bl = this.compileMulti({ type: 3 /* Multi */, content: ast.body }, subCtx);
4333
+ if (bl) {
4320
4334
  this.helpers.add("zero");
4321
- this.addLine(`${ctxVar}[zero] = b${nextId};`);
4335
+ this.addLine(`${ctxVar}[zero] = ${bl};`);
4322
4336
  }
4323
4337
  }
4324
4338
  const isDynamic = INTERP_REGEXP.test(ast.name);
@@ -4353,6 +4367,7 @@
4353
4367
  if (ast.body && !ctx.isLast) {
4354
4368
  this.addLine(`${ctxVar} = ${ctxVar}.__proto__;`);
4355
4369
  }
4370
+ return block.varName;
4356
4371
  }
4357
4372
  compileTCallBlock(ast, ctx) {
4358
4373
  let { block, forceNewBlock } = ctx;
@@ -4363,6 +4378,7 @@
4363
4378
  }
4364
4379
  block = this.createBlock(block, "multi", ctx);
4365
4380
  this.insertBlock(compileExpr(ast.name), block, { ...ctx, forceNewBlock: !block });
4381
+ return block.varName;
4366
4382
  }
4367
4383
  compileTSet(ast, ctx) {
4368
4384
  this.target.shouldProtectScope = true;
@@ -4372,7 +4388,8 @@
4372
4388
  this.helpers.add("LazyValue");
4373
4389
  const bodyAst = { type: 3 /* Multi */, content: ast.body };
4374
4390
  const name = this.compileInNewTarget("value", bodyAst, ctx);
4375
- let value = `new LazyValue(${name}, ctx, this, node)`;
4391
+ let key = this.target.currentKey(ctx);
4392
+ let value = `new LazyValue(${name}, ctx, this, node, ${key})`;
4376
4393
  value = ast.value ? (value ? `withDefault(${expr}, ${value})` : expr) : value;
4377
4394
  this.addLine(`ctx[\`${ast.name}\`] = ${value};`);
4378
4395
  }
@@ -4392,6 +4409,7 @@
4392
4409
  this.helpers.add("setContextValue");
4393
4410
  this.addLine(`setContextValue(${ctx.ctxVar || "ctx"}, "${ast.name}", ${value});`);
4394
4411
  }
4412
+ return null;
4395
4413
  }
4396
4414
  generateComponentKey() {
4397
4415
  const parts = [generateId("__")];
@@ -4497,7 +4515,7 @@
4497
4515
  expr = `\`${ast.name}\``;
4498
4516
  }
4499
4517
  if (this.dev) {
4500
- this.addLine(`helpers.validateProps(${expr}, ${propVar}, ctx);`);
4518
+ this.addLine(`helpers.validateProps(${expr}, ${propVar}, this);`);
4501
4519
  }
4502
4520
  if (block && (ctx.forceNewBlock === false || ctx.tKeyExpr)) {
4503
4521
  // todo: check the forcenewblock condition
@@ -4522,6 +4540,7 @@
4522
4540
  }
4523
4541
  block = this.createBlock(block, "multi", ctx);
4524
4542
  this.insertBlock(blockExpr, block, ctx);
4543
+ return block.varName;
4525
4544
  }
4526
4545
  wrapWithEventCatcher(expr, on) {
4527
4546
  this.helpers.add("createCatcher");
@@ -4588,11 +4607,13 @@
4588
4607
  }
4589
4608
  block = this.createBlock(block, "multi", ctx);
4590
4609
  this.insertBlock(blockString, block, { ...ctx, forceNewBlock: false });
4610
+ return block.varName;
4591
4611
  }
4592
4612
  compileTTranslation(ast, ctx) {
4593
4613
  if (ast.content) {
4594
- this.compileAST(ast.content, Object.assign({}, ctx, { translate: false }));
4614
+ return this.compileAST(ast.content, Object.assign({}, ctx, { translate: false }));
4595
4615
  }
4616
+ return null;
4596
4617
  }
4597
4618
  compileTPortal(ast, ctx) {
4598
4619
  if (!this.staticDefs.find((d) => d.id === "Portal")) {
@@ -4619,6 +4640,7 @@
4619
4640
  }
4620
4641
  block = this.createBlock(block, "multi", ctx);
4621
4642
  this.insertBlock(blockString, block, { ...ctx, forceNewBlock: false });
4643
+ return block.varName;
4622
4644
  }
4623
4645
  }
4624
4646
 
@@ -5788,9 +5810,9 @@ See https://github.com/odoo/owl/blob/${hash}/doc/reference/app.md#configuration
5788
5810
  Object.defineProperty(exports, '__esModule', { value: true });
5789
5811
 
5790
5812
 
5791
- __info__.version = '2.0.0-beta-20';
5792
- __info__.date = '2022-09-09T07:26:24.123Z';
5793
- __info__.hash = 'b51756f';
5813
+ __info__.version = '2.0.0-beta-22';
5814
+ __info__.date = '2022-09-29T07:17:18.044Z';
5815
+ __info__.hash = '64bad25';
5794
5816
  __info__.url = 'https://github.com/odoo/owl';
5795
5817
 
5796
5818