@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.es.js CHANGED
@@ -672,6 +672,15 @@ function buildTree(node, parent = null, domParentTree = null) {
672
672
  : document.createElement(tagName);
673
673
  }
674
674
  if (el instanceof Element) {
675
+ if (!domParentTree) {
676
+ // some html elements may have side effects when setting their attributes.
677
+ // For example, setting the src attribute of an <img/> will trigger a
678
+ // request to get the corresponding image. This is something that we
679
+ // don't want at compile time. We avoid that by putting the content of
680
+ // the block in a <template/> element
681
+ const fragment = document.createElement("template").content;
682
+ fragment.appendChild(el);
683
+ }
675
684
  for (let i = 0; i < attrs.length; i++) {
676
685
  const attrName = attrs[i].name;
677
686
  const attrValue = attrs[i].value;
@@ -2596,67 +2605,71 @@ Component.template = "";
2596
2605
 
2597
2606
  const VText = text("").constructor;
2598
2607
  class VPortal extends VText {
2599
- constructor(selector, realBDom) {
2608
+ constructor(selector, content) {
2600
2609
  super("");
2601
2610
  this.target = null;
2602
2611
  this.selector = selector;
2603
- this.realBDom = realBDom;
2612
+ this.content = content;
2604
2613
  }
2605
2614
  mount(parent, anchor) {
2606
2615
  super.mount(parent, anchor);
2607
2616
  this.target = document.querySelector(this.selector);
2608
- if (!this.target) {
2609
- let el = this.el;
2610
- while (el && el.parentElement instanceof HTMLElement) {
2611
- el = el.parentElement;
2612
- }
2613
- this.target = el && el.querySelector(this.selector);
2614
- if (!this.target) {
2615
- throw new OwlError("invalid portal target");
2616
- }
2617
+ if (this.target) {
2618
+ this.content.mount(this.target, null);
2619
+ }
2620
+ else {
2621
+ this.content.mount(parent, anchor);
2617
2622
  }
2618
- this.realBDom.mount(this.target, null);
2619
2623
  }
2620
2624
  beforeRemove() {
2621
- this.realBDom.beforeRemove();
2625
+ this.content.beforeRemove();
2622
2626
  }
2623
2627
  remove() {
2624
- if (this.realBDom) {
2628
+ if (this.content) {
2625
2629
  super.remove();
2626
- this.realBDom.remove();
2627
- this.realBDom = null;
2630
+ this.content.remove();
2631
+ this.content = null;
2628
2632
  }
2629
2633
  }
2630
2634
  patch(other) {
2631
2635
  super.patch(other);
2632
- if (this.realBDom) {
2633
- this.realBDom.patch(other.realBDom, true);
2636
+ if (this.content) {
2637
+ this.content.patch(other.content, true);
2634
2638
  }
2635
2639
  else {
2636
- this.realBDom = other.realBDom;
2637
- this.realBDom.mount(this.target, null);
2640
+ this.content = other.content;
2641
+ this.content.mount(this.target, null);
2638
2642
  }
2639
2643
  }
2640
2644
  }
2641
2645
  /**
2642
- * <t t-slot="default"/>
2646
+ * kind of similar to <t t-slot="default"/>, but it wraps it around a VPortal
2643
2647
  */
2644
2648
  function portalTemplate(app, bdom, helpers) {
2645
2649
  let { callSlot } = helpers;
2646
2650
  return function template(ctx, node, key = "") {
2647
- return callSlot(ctx, node, key, "default", false, null);
2651
+ return new VPortal(ctx.props.target, callSlot(ctx, node, key, "default", false, null));
2648
2652
  };
2649
2653
  }
2650
2654
  class Portal extends Component {
2651
2655
  setup() {
2652
2656
  const node = this.__owl__;
2653
- const renderFn = node.renderFn;
2654
- node.renderFn = () => new VPortal(this.props.target, renderFn());
2655
- onWillUnmount(() => {
2656
- if (node.bdom) {
2657
- node.bdom.remove();
2657
+ onMounted(() => {
2658
+ const portal = node.bdom;
2659
+ if (!portal.target) {
2660
+ const target = document.querySelector(this.props.target);
2661
+ if (target) {
2662
+ portal.content.moveBefore(target, null);
2663
+ }
2664
+ else {
2665
+ throw new OwlError("invalid portal target");
2666
+ }
2658
2667
  }
2659
2668
  });
2669
+ onWillUnmount(() => {
2670
+ const portal = node.bdom;
2671
+ portal.remove();
2672
+ });
2660
2673
  }
2661
2674
  }
2662
2675
  Portal.template = "__portal__";
@@ -2890,14 +2903,15 @@ function shallowEqual(l1, l2) {
2890
2903
  return true;
2891
2904
  }
2892
2905
  class LazyValue {
2893
- constructor(fn, ctx, component, node) {
2906
+ constructor(fn, ctx, component, node, key) {
2894
2907
  this.fn = fn;
2895
2908
  this.ctx = capture(ctx);
2896
2909
  this.component = component;
2897
2910
  this.node = node;
2911
+ this.key = key;
2898
2912
  }
2899
2913
  evaluate() {
2900
- return this.fn.call(this.component, this.ctx, this.node);
2914
+ return this.fn.call(this.component, this.ctx, this.node, this.key);
2901
2915
  }
2902
2916
  toString() {
2903
2917
  return this.evaluate().toString();
@@ -2979,10 +2993,10 @@ function multiRefSetter(refs, name) {
2979
2993
  * visit recursively the props and all the children to check if they are valid.
2980
2994
  * This is why it is only done in 'dev' mode.
2981
2995
  */
2982
- function validateProps(name, props, parent) {
2996
+ function validateProps(name, props, comp) {
2983
2997
  const ComponentClass = typeof name !== "string"
2984
2998
  ? name
2985
- : parent.constructor.components[name];
2999
+ : comp.constructor.components[name];
2986
3000
  if (!ComponentClass) {
2987
3001
  // this is an error, wrong component. We silently return here instead so the
2988
3002
  // error is triggered by the usual path ('component' function)
@@ -2990,7 +3004,7 @@ function validateProps(name, props, parent) {
2990
3004
  }
2991
3005
  const schema = ComponentClass.props;
2992
3006
  if (!schema) {
2993
- if (parent.__owl__.app.warnIfNoStaticProps) {
3007
+ if (comp.__owl__.app.warnIfNoStaticProps) {
2994
3008
  console.warn(`Component '${ComponentClass.name}' does not have a static props description`);
2995
3009
  }
2996
3010
  return;
@@ -3583,6 +3597,13 @@ class CodeTarget {
3583
3597
  result.push(`}`);
3584
3598
  return result.join("\n ");
3585
3599
  }
3600
+ currentKey(ctx) {
3601
+ let key = this.loopLevel ? `key${this.loopLevel}` : "key";
3602
+ if (ctx.tKeyExpr) {
3603
+ key = `${ctx.tKeyExpr} + ${key}`;
3604
+ }
3605
+ return key;
3606
+ }
3586
3607
  }
3587
3608
  const TRANSLATABLE_ATTRS = ["label", "title", "placeholder", "alt"];
3588
3609
  const translationRE = /^(\s*)([\s\S]+?)(\s*)$/;
@@ -3712,18 +3733,14 @@ class CodeGenerator {
3712
3733
  }
3713
3734
  insertBlock(expression, block, ctx) {
3714
3735
  let blockExpr = block.generateExpr(expression);
3715
- const tKeyExpr = ctx.tKeyExpr;
3716
3736
  if (block.parentVar) {
3717
- let keyArg = `key${this.target.loopLevel}`;
3718
- if (tKeyExpr) {
3719
- keyArg = `${tKeyExpr} + ${keyArg}`;
3720
- }
3737
+ let key = this.target.currentKey(ctx);
3721
3738
  this.helpers.add("withKey");
3722
- this.addLine(`${block.parentVar}[${ctx.index}] = withKey(${blockExpr}, ${keyArg});`);
3739
+ this.addLine(`${block.parentVar}[${ctx.index}] = withKey(${blockExpr}, ${key});`);
3723
3740
  return;
3724
3741
  }
3725
- if (tKeyExpr) {
3726
- blockExpr = `toggler(${tKeyExpr}, ${blockExpr})`;
3742
+ if (ctx.tKeyExpr) {
3743
+ blockExpr = `toggler(${ctx.tKeyExpr}, ${blockExpr})`;
3727
3744
  }
3728
3745
  if (block.isRoot && !ctx.preventRoot) {
3729
3746
  if (this.target.on) {
@@ -3768,74 +3785,62 @@ class CodeGenerator {
3768
3785
  })
3769
3786
  .join("");
3770
3787
  }
3788
+ /**
3789
+ * @returns the newly created block name, if any
3790
+ */
3771
3791
  compileAST(ast, ctx) {
3772
3792
  switch (ast.type) {
3773
3793
  case 1 /* Comment */:
3774
- this.compileComment(ast, ctx);
3775
- break;
3794
+ return this.compileComment(ast, ctx);
3776
3795
  case 0 /* Text */:
3777
- this.compileText(ast, ctx);
3778
- break;
3796
+ return this.compileText(ast, ctx);
3779
3797
  case 2 /* DomNode */:
3780
- this.compileTDomNode(ast, ctx);
3781
- break;
3798
+ return this.compileTDomNode(ast, ctx);
3782
3799
  case 4 /* TEsc */:
3783
- this.compileTEsc(ast, ctx);
3784
- break;
3800
+ return this.compileTEsc(ast, ctx);
3785
3801
  case 8 /* TOut */:
3786
- this.compileTOut(ast, ctx);
3787
- break;
3802
+ return this.compileTOut(ast, ctx);
3788
3803
  case 5 /* TIf */:
3789
- this.compileTIf(ast, ctx);
3790
- break;
3804
+ return this.compileTIf(ast, ctx);
3791
3805
  case 9 /* TForEach */:
3792
- this.compileTForeach(ast, ctx);
3793
- break;
3806
+ return this.compileTForeach(ast, ctx);
3794
3807
  case 10 /* TKey */:
3795
- this.compileTKey(ast, ctx);
3796
- break;
3808
+ return this.compileTKey(ast, ctx);
3797
3809
  case 3 /* Multi */:
3798
- this.compileMulti(ast, ctx);
3799
- break;
3810
+ return this.compileMulti(ast, ctx);
3800
3811
  case 7 /* TCall */:
3801
- this.compileTCall(ast, ctx);
3802
- break;
3812
+ return this.compileTCall(ast, ctx);
3803
3813
  case 15 /* TCallBlock */:
3804
- this.compileTCallBlock(ast, ctx);
3805
- break;
3814
+ return this.compileTCallBlock(ast, ctx);
3806
3815
  case 6 /* TSet */:
3807
- this.compileTSet(ast, ctx);
3808
- break;
3816
+ return this.compileTSet(ast, ctx);
3809
3817
  case 11 /* TComponent */:
3810
- this.compileComponent(ast, ctx);
3811
- break;
3818
+ return this.compileComponent(ast, ctx);
3812
3819
  case 12 /* TDebug */:
3813
- this.compileDebug(ast, ctx);
3814
- break;
3820
+ return this.compileDebug(ast, ctx);
3815
3821
  case 13 /* TLog */:
3816
- this.compileLog(ast, ctx);
3817
- break;
3822
+ return this.compileLog(ast, ctx);
3818
3823
  case 14 /* TSlot */:
3819
- this.compileTSlot(ast, ctx);
3820
- break;
3824
+ return this.compileTSlot(ast, ctx);
3821
3825
  case 16 /* TTranslation */:
3822
- this.compileTTranslation(ast, ctx);
3823
- break;
3826
+ return this.compileTTranslation(ast, ctx);
3824
3827
  case 17 /* TPortal */:
3825
- this.compileTPortal(ast, ctx);
3828
+ return this.compileTPortal(ast, ctx);
3826
3829
  }
3827
3830
  }
3828
3831
  compileDebug(ast, ctx) {
3829
3832
  this.addLine(`debugger;`);
3830
3833
  if (ast.content) {
3831
- this.compileAST(ast.content, ctx);
3834
+ return this.compileAST(ast.content, ctx);
3832
3835
  }
3836
+ return null;
3833
3837
  }
3834
3838
  compileLog(ast, ctx) {
3835
3839
  this.addLine(`console.log(${compileExpr(ast.expr)});`);
3836
3840
  if (ast.content) {
3837
- this.compileAST(ast.content, ctx);
3841
+ return this.compileAST(ast.content, ctx);
3838
3842
  }
3843
+ return null;
3839
3844
  }
3840
3845
  compileComment(ast, ctx) {
3841
3846
  let { block, forceNewBlock } = ctx;
@@ -3851,6 +3856,7 @@ class CodeGenerator {
3851
3856
  const text = xmlDoc.createComment(ast.value);
3852
3857
  block.insert(text);
3853
3858
  }
3859
+ return block.varName;
3854
3860
  }
3855
3861
  compileText(ast, ctx) {
3856
3862
  let { block, forceNewBlock } = ctx;
@@ -3870,6 +3876,7 @@ class CodeGenerator {
3870
3876
  const createFn = ast.type === 0 /* Text */ ? xmlDoc.createTextNode : xmlDoc.createComment;
3871
3877
  block.insert(createFn.call(xmlDoc, value));
3872
3878
  }
3879
+ return block.varName;
3873
3880
  }
3874
3881
  generateHandlerCode(rawEvent, handler) {
3875
3882
  const modifiers = rawEvent
@@ -4062,6 +4069,7 @@ class CodeGenerator {
4062
4069
  this.addLine(`let ${block.children.map((c) => c.varName)};`, codeIdx);
4063
4070
  }
4064
4071
  }
4072
+ return block.varName;
4065
4073
  }
4066
4074
  compileTEsc(ast, ctx) {
4067
4075
  let { block, forceNewBlock } = ctx;
@@ -4086,6 +4094,7 @@ class CodeGenerator {
4086
4094
  const text = xmlDoc.createElement(`block-text-${idx}`);
4087
4095
  block.insert(text);
4088
4096
  }
4097
+ return block.varName;
4089
4098
  }
4090
4099
  compileTOut(ast, ctx) {
4091
4100
  let { block } = ctx;
@@ -4111,6 +4120,7 @@ class CodeGenerator {
4111
4120
  blockStr = `safeOutput(${compileExpr(ast.expr)})`;
4112
4121
  }
4113
4122
  this.insertBlock(blockStr, block, ctx);
4123
+ return block.varName;
4114
4124
  }
4115
4125
  compileTIfBranch(content, block, ctx) {
4116
4126
  this.target.indentLevel++;
@@ -4165,6 +4175,7 @@ class CodeGenerator {
4165
4175
  const args = block.children.map((c) => c.varName).join(", ");
4166
4176
  this.insertBlock(`multi([${args}])`, block, ctx);
4167
4177
  }
4178
+ return block.varName;
4168
4179
  }
4169
4180
  compileTForeach(ast, ctx) {
4170
4181
  let { block } = ctx;
@@ -4237,6 +4248,7 @@ class CodeGenerator {
4237
4248
  this.addLine(`ctx = ctx.__proto__;`);
4238
4249
  }
4239
4250
  this.insertBlock("l", block, ctx);
4251
+ return block.varName;
4240
4252
  }
4241
4253
  compileTKey(ast, ctx) {
4242
4254
  const tKeyExpr = generateId("tKey_");
@@ -4246,7 +4258,7 @@ class CodeGenerator {
4246
4258
  block: ctx.block,
4247
4259
  index: ctx.index,
4248
4260
  });
4249
- this.compileAST(ast.content, ctx);
4261
+ return this.compileAST(ast.content, ctx);
4250
4262
  }
4251
4263
  compileMulti(ast, ctx) {
4252
4264
  let { block, forceNewBlock } = ctx;
@@ -4254,11 +4266,13 @@ class CodeGenerator {
4254
4266
  let codeIdx = this.target.code.length;
4255
4267
  if (isNewBlock) {
4256
4268
  const n = ast.content.filter((c) => c.type !== 6 /* TSet */).length;
4269
+ let result = null;
4257
4270
  if (n <= 1) {
4258
4271
  for (let child of ast.content) {
4259
- this.compileAST(child, ctx);
4272
+ const blockName = this.compileAST(child, ctx);
4273
+ result = result || blockName;
4260
4274
  }
4261
- return;
4275
+ return result;
4262
4276
  }
4263
4277
  block = this.createBlock(block, "multi", ctx);
4264
4278
  }
@@ -4298,6 +4312,7 @@ class CodeGenerator {
4298
4312
  const args = block.children.map((c) => c.varName).join(", ");
4299
4313
  this.insertBlock(`multi([${args}])`, block, ctx);
4300
4314
  }
4315
+ return block.varName;
4301
4316
  }
4302
4317
  compileTCall(ast, ctx) {
4303
4318
  let { block, forceNewBlock } = ctx;
@@ -4310,12 +4325,11 @@ class CodeGenerator {
4310
4325
  this.addLine(`${ctxVar} = Object.create(${ctxVar});`);
4311
4326
  this.addLine(`${ctxVar}[isBoundary] = 1;`);
4312
4327
  this.helpers.add("isBoundary");
4313
- const nextId = BlockDescription.nextBlockId;
4314
4328
  const subCtx = createContext(ctx, { preventRoot: true, ctxVar });
4315
- this.compileAST({ type: 3 /* Multi */, content: ast.body }, subCtx);
4316
- if (nextId !== BlockDescription.nextBlockId) {
4329
+ const bl = this.compileMulti({ type: 3 /* Multi */, content: ast.body }, subCtx);
4330
+ if (bl) {
4317
4331
  this.helpers.add("zero");
4318
- this.addLine(`${ctxVar}[zero] = b${nextId};`);
4332
+ this.addLine(`${ctxVar}[zero] = ${bl};`);
4319
4333
  }
4320
4334
  }
4321
4335
  const isDynamic = INTERP_REGEXP.test(ast.name);
@@ -4350,6 +4364,7 @@ class CodeGenerator {
4350
4364
  if (ast.body && !ctx.isLast) {
4351
4365
  this.addLine(`${ctxVar} = ${ctxVar}.__proto__;`);
4352
4366
  }
4367
+ return block.varName;
4353
4368
  }
4354
4369
  compileTCallBlock(ast, ctx) {
4355
4370
  let { block, forceNewBlock } = ctx;
@@ -4360,6 +4375,7 @@ class CodeGenerator {
4360
4375
  }
4361
4376
  block = this.createBlock(block, "multi", ctx);
4362
4377
  this.insertBlock(compileExpr(ast.name), block, { ...ctx, forceNewBlock: !block });
4378
+ return block.varName;
4363
4379
  }
4364
4380
  compileTSet(ast, ctx) {
4365
4381
  this.target.shouldProtectScope = true;
@@ -4369,7 +4385,8 @@ class CodeGenerator {
4369
4385
  this.helpers.add("LazyValue");
4370
4386
  const bodyAst = { type: 3 /* Multi */, content: ast.body };
4371
4387
  const name = this.compileInNewTarget("value", bodyAst, ctx);
4372
- let value = `new LazyValue(${name}, ctx, this, node)`;
4388
+ let key = this.target.currentKey(ctx);
4389
+ let value = `new LazyValue(${name}, ctx, this, node, ${key})`;
4373
4390
  value = ast.value ? (value ? `withDefault(${expr}, ${value})` : expr) : value;
4374
4391
  this.addLine(`ctx[\`${ast.name}\`] = ${value};`);
4375
4392
  }
@@ -4389,6 +4406,7 @@ class CodeGenerator {
4389
4406
  this.helpers.add("setContextValue");
4390
4407
  this.addLine(`setContextValue(${ctx.ctxVar || "ctx"}, "${ast.name}", ${value});`);
4391
4408
  }
4409
+ return null;
4392
4410
  }
4393
4411
  generateComponentKey() {
4394
4412
  const parts = [generateId("__")];
@@ -4494,7 +4512,7 @@ class CodeGenerator {
4494
4512
  expr = `\`${ast.name}\``;
4495
4513
  }
4496
4514
  if (this.dev) {
4497
- this.addLine(`helpers.validateProps(${expr}, ${propVar}, ctx);`);
4515
+ this.addLine(`helpers.validateProps(${expr}, ${propVar}, this);`);
4498
4516
  }
4499
4517
  if (block && (ctx.forceNewBlock === false || ctx.tKeyExpr)) {
4500
4518
  // todo: check the forcenewblock condition
@@ -4519,6 +4537,7 @@ class CodeGenerator {
4519
4537
  }
4520
4538
  block = this.createBlock(block, "multi", ctx);
4521
4539
  this.insertBlock(blockExpr, block, ctx);
4540
+ return block.varName;
4522
4541
  }
4523
4542
  wrapWithEventCatcher(expr, on) {
4524
4543
  this.helpers.add("createCatcher");
@@ -4585,11 +4604,13 @@ class CodeGenerator {
4585
4604
  }
4586
4605
  block = this.createBlock(block, "multi", ctx);
4587
4606
  this.insertBlock(blockString, block, { ...ctx, forceNewBlock: false });
4607
+ return block.varName;
4588
4608
  }
4589
4609
  compileTTranslation(ast, ctx) {
4590
4610
  if (ast.content) {
4591
- this.compileAST(ast.content, Object.assign({}, ctx, { translate: false }));
4611
+ return this.compileAST(ast.content, Object.assign({}, ctx, { translate: false }));
4592
4612
  }
4613
+ return null;
4593
4614
  }
4594
4615
  compileTPortal(ast, ctx) {
4595
4616
  if (!this.staticDefs.find((d) => d.id === "Portal")) {
@@ -4616,6 +4637,7 @@ class CodeGenerator {
4616
4637
  }
4617
4638
  block = this.createBlock(block, "multi", ctx);
4618
4639
  this.insertBlock(blockString, block, { ...ctx, forceNewBlock: false });
4640
+ return block.varName;
4619
4641
  }
4620
4642
  }
4621
4643
 
@@ -5750,7 +5772,7 @@ TemplateSet.prototype._compileTemplate = function _compileTemplate(name, templat
5750
5772
  export { App, Component, EventBus, OwlError, __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 };
5751
5773
 
5752
5774
 
5753
- __info__.version = '2.0.0-beta-20';
5754
- __info__.date = '2022-09-09T07:26:24.123Z';
5755
- __info__.hash = 'b51756f';
5775
+ __info__.version = '2.0.0-beta-22';
5776
+ __info__.date = '2022-09-29T07:17:18.044Z';
5777
+ __info__.hash = '64bad25';
5756
5778
  __info__.url = 'https://github.com/odoo/owl';