@odoo/owl 2.0.7 → 2.0.8

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.cjs.js CHANGED
@@ -280,32 +280,6 @@ function updateClass(val, oldVal) {
280
280
  tokenListAdd.call(cl, c);
281
281
  }
282
282
  }
283
- }
284
- function makePropSetter(name) {
285
- return function setProp(value) {
286
- // support 0, fallback to empty string for other falsy values
287
- this[name] = value === 0 ? 0 : value ? value.valueOf() : "";
288
- };
289
- }
290
- function isProp(tag, key) {
291
- switch (tag) {
292
- case "input":
293
- return (key === "checked" ||
294
- key === "indeterminate" ||
295
- key === "value" ||
296
- key === "readonly" ||
297
- key === "disabled");
298
- case "option":
299
- return key === "selected" || key === "disabled";
300
- case "textarea":
301
- return key === "value" || key === "readonly" || key === "disabled";
302
- case "select":
303
- return key === "value" || key === "disabled";
304
- case "button":
305
- case "optgroup":
306
- return key === "disabled";
307
- }
308
- return false;
309
283
  }
310
284
 
311
285
  function createEventHandler(rawEvent) {
@@ -609,6 +583,12 @@ const characterDataSetData = getDescriptor$1(characterDataProto, "data").set;
609
583
  const nodeGetFirstChild = getDescriptor$1(nodeProto$2, "firstChild").get;
610
584
  const nodeGetNextSibling = getDescriptor$1(nodeProto$2, "nextSibling").get;
611
585
  const NO_OP = () => { };
586
+ function makePropSetter(name) {
587
+ return function setProp(value) {
588
+ // support 0, fallback to empty string for other falsy values
589
+ this[name] = value === 0 ? 0 : value ? value.valueOf() : "";
590
+ };
591
+ }
612
592
  const cache$1 = {};
613
593
  /**
614
594
  * Compiling blocks is a multi-step process:
@@ -726,6 +706,15 @@ function buildTree(node, parent = null, domParentTree = null) {
726
706
  tag: tagName,
727
707
  });
728
708
  }
709
+ else if (attrName.startsWith("block-property-")) {
710
+ const idx = parseInt(attrName.slice(15), 10);
711
+ info.push({
712
+ type: "property",
713
+ idx,
714
+ name: attrValue,
715
+ tag: tagName,
716
+ });
717
+ }
729
718
  else if (attrName === "block-attributes") {
730
719
  info.push({
731
720
  type: "attributes",
@@ -872,16 +861,22 @@ function updateCtx(ctx, tree) {
872
861
  };
873
862
  }
874
863
  break;
864
+ case "property": {
865
+ const refIdx = info.refIdx;
866
+ const setProp = makePropSetter(info.name);
867
+ ctx.locations.push({
868
+ idx: info.idx,
869
+ refIdx,
870
+ setData: setProp,
871
+ updateData: setProp,
872
+ });
873
+ break;
874
+ }
875
875
  case "attribute": {
876
876
  const refIdx = info.refIdx;
877
877
  let updater;
878
878
  let setter;
879
- if (isProp(info.tag, info.name)) {
880
- const setProp = makePropSetter(info.name);
881
- setter = setProp;
882
- updater = setProp;
883
- }
884
- else if (info.name === "class") {
879
+ if (info.name === "class") {
885
880
  setter = setClass;
886
881
  updater = updateClass;
887
882
  }
@@ -2486,6 +2481,18 @@ class ComponentNode {
2486
2481
  this.fiber = null;
2487
2482
  }
2488
2483
  }
2484
+ /**
2485
+ * Sets a ref to a given HTMLElement.
2486
+ *
2487
+ * @param name the name of the ref to set
2488
+ * @param el the HTMLElement to set the ref to. The ref is not set if the el
2489
+ * is null, but useRef will not return elements that are not in the DOM
2490
+ */
2491
+ setRef(name, el) {
2492
+ if (el) {
2493
+ this.refs[name] = el;
2494
+ }
2495
+ }
2489
2496
  // ---------------------------------------------------------------------------
2490
2497
  // Block DOM methods
2491
2498
  // ---------------------------------------------------------------------------
@@ -3021,45 +3028,6 @@ function safeOutput(value, defaultValue) {
3021
3028
  }
3022
3029
  return toggler(safeKey, block);
3023
3030
  }
3024
- let boundFunctions = new WeakMap();
3025
- const WeakMapGet = WeakMap.prototype.get;
3026
- const WeakMapSet = WeakMap.prototype.set;
3027
- function bind(component, fn) {
3028
- let boundFnMap = WeakMapGet.call(boundFunctions, component);
3029
- if (!boundFnMap) {
3030
- boundFnMap = new WeakMap();
3031
- WeakMapSet.call(boundFunctions, component, boundFnMap);
3032
- }
3033
- let boundFn = WeakMapGet.call(boundFnMap, fn);
3034
- if (!boundFn) {
3035
- boundFn = fn.bind(component);
3036
- WeakMapSet.call(boundFnMap, fn, boundFn);
3037
- }
3038
- return boundFn;
3039
- }
3040
- function multiRefSetter(refs, name) {
3041
- let count = 0;
3042
- return (el) => {
3043
- if (el) {
3044
- count++;
3045
- if (count > 1) {
3046
- throw new OwlError("Cannot have 2 elements with same ref name at the same time");
3047
- }
3048
- }
3049
- if (count === 0 || el) {
3050
- refs[name] = el;
3051
- }
3052
- };
3053
- }
3054
- function singleRefSetter(refs, name) {
3055
- let _el = null;
3056
- return (el) => {
3057
- if (el || refs[name] === _el) {
3058
- refs[name] = el;
3059
- _el = el;
3060
- }
3061
- };
3062
- }
3063
3031
  /**
3064
3032
  * Validate the component props (or next props) against the (static) props
3065
3033
  * description. This is potentially an expensive operation: it may needs to
@@ -3098,6 +3066,16 @@ function validateProps(name, props, comp) {
3098
3066
  throw new OwlError(`Invalid props for component '${ComponentClass.name}': ` + errors.join(", "));
3099
3067
  }
3100
3068
  }
3069
+ function makeRefWrapper(node) {
3070
+ let refNames = new Set();
3071
+ return (name, fn) => {
3072
+ if (refNames.has(name)) {
3073
+ throw new OwlError(`Cannot set the same ref more than once in the same component, ref "${name}" was set multiple times in ${node.name}`);
3074
+ }
3075
+ refNames.add(name);
3076
+ return fn;
3077
+ };
3078
+ }
3101
3079
  const helpers = {
3102
3080
  withDefault,
3103
3081
  zero: Symbol("zero"),
@@ -3107,17 +3085,15 @@ const helpers = {
3107
3085
  withKey,
3108
3086
  prepareList,
3109
3087
  setContextValue,
3110
- multiRefSetter,
3111
- singleRefSetter,
3112
3088
  shallowEqual,
3113
3089
  toNumber,
3114
3090
  validateProps,
3115
3091
  LazyValue,
3116
3092
  safeOutput,
3117
- bind,
3118
3093
  createCatcher,
3119
3094
  markRaw,
3120
3095
  OwlError,
3096
+ makeRefWrapper,
3121
3097
  };
3122
3098
 
3123
3099
  const bdom = { text, createBlock, list, multi, html, toggler, comment };
@@ -3544,6 +3520,7 @@ function interpolate(s) {
3544
3520
  return replaceDynamicParts(s, compileExpr);
3545
3521
  }
3546
3522
 
3523
+ const whitespaceRE = /\s+/g;
3547
3524
  // using a non-html document so that <inner/outer>HTML serializes as XML instead
3548
3525
  // of HTML (as we will parse it as xml later)
3549
3526
  const xmlDoc = document.implementation.createDocument(null, null, null);
@@ -3553,6 +3530,27 @@ function generateId(prefix = "") {
3553
3530
  nextDataIds[prefix] = (nextDataIds[prefix] || 0) + 1;
3554
3531
  return prefix + nextDataIds[prefix];
3555
3532
  }
3533
+ function isProp(tag, key) {
3534
+ switch (tag) {
3535
+ case "input":
3536
+ return (key === "checked" ||
3537
+ key === "indeterminate" ||
3538
+ key === "value" ||
3539
+ key === "readonly" ||
3540
+ key === "readOnly" ||
3541
+ key === "disabled");
3542
+ case "option":
3543
+ return key === "selected" || key === "disabled";
3544
+ case "textarea":
3545
+ return key === "value" || key === "readonly" || key === "readOnly" || key === "disabled";
3546
+ case "select":
3547
+ return key === "value" || key === "disabled";
3548
+ case "button":
3549
+ case "optgroup":
3550
+ return key === "disabled";
3551
+ }
3552
+ return false;
3553
+ }
3556
3554
  // -----------------------------------------------------------------------------
3557
3555
  // BlockDescription
3558
3556
  // -----------------------------------------------------------------------------
@@ -3628,10 +3626,8 @@ class CodeTarget {
3628
3626
  this.code = [];
3629
3627
  this.hasRoot = false;
3630
3628
  this.hasCache = false;
3631
- this.hasRef = false;
3632
- // maps ref name to [id, expr]
3633
- this.refInfo = {};
3634
3629
  this.shouldProtectScope = false;
3630
+ this.hasRefWrapper = false;
3635
3631
  this.name = name;
3636
3632
  this.on = on || null;
3637
3633
  }
@@ -3647,17 +3643,13 @@ class CodeTarget {
3647
3643
  generateCode() {
3648
3644
  let result = [];
3649
3645
  result.push(`function ${this.name}(ctx, node, key = "") {`);
3650
- if (this.hasRef) {
3651
- result.push(` const refs = this.__owl__.refs;`);
3652
- for (let name in this.refInfo) {
3653
- const [id, expr] = this.refInfo[name];
3654
- result.push(` const ${id} = ${expr};`);
3655
- }
3656
- }
3657
3646
  if (this.shouldProtectScope) {
3658
3647
  result.push(` ctx = Object.create(ctx);`);
3659
3648
  result.push(` ctx[isBoundary] = 1`);
3660
3649
  }
3650
+ if (this.hasRefWrapper) {
3651
+ result.push(` let refWrapper = makeRefWrapper(this.__owl__);`);
3652
+ }
3661
3653
  if (this.hasCache) {
3662
3654
  result.push(` let cache = ctx.cache || {};`);
3663
3655
  result.push(` let nextCache = ctx.cache = {};`);
@@ -3939,6 +3931,9 @@ class CodeGenerator {
3939
3931
  const match = translationRE.exec(value);
3940
3932
  value = match[1] + this.translateFn(match[2]) + match[3];
3941
3933
  }
3934
+ if (!ctx.inPreTag) {
3935
+ value = value.replace(whitespaceRE, " ");
3936
+ }
3942
3937
  if (!block || forceNewBlock) {
3943
3938
  block = this.createBlock(block, "text", ctx);
3944
3939
  this.insertBlock(`text(\`${value}\`)`, block, {
@@ -4003,21 +3998,29 @@ class CodeGenerator {
4003
3998
  attrName = key === "t-att" ? null : key.slice(6);
4004
3999
  expr = compileExpr(ast.attrs[key]);
4005
4000
  if (attrName && isProp(ast.tag, attrName)) {
4001
+ if (attrName === "readonly") {
4002
+ // the property has a different name than the attribute
4003
+ attrName = "readOnly";
4004
+ }
4006
4005
  // we force a new string or new boolean to bypass the equality check in blockdom when patching same value
4007
4006
  if (attrName === "value") {
4008
- // When the expression is falsy, fall back to an empty string
4009
- expr = `new String((${expr}) || "")`;
4007
+ // When the expression is falsy (except 0), fall back to an empty string
4008
+ expr = `new String((${expr}) === 0 ? 0 : ((${expr}) || ""))`;
4010
4009
  }
4011
4010
  else {
4012
4011
  expr = `new Boolean(${expr})`;
4013
4012
  }
4014
- }
4015
- const idx = block.insertData(expr, "attr");
4016
- if (key === "t-att") {
4017
- attrs[`block-attributes`] = String(idx);
4013
+ const idx = block.insertData(expr, "prop");
4014
+ attrs[`block-property-${idx}`] = attrName;
4018
4015
  }
4019
4016
  else {
4020
- attrs[`block-attribute-${idx}`] = attrName;
4017
+ const idx = block.insertData(expr, "attr");
4018
+ if (key === "t-att") {
4019
+ attrs[`block-attributes`] = String(idx);
4020
+ }
4021
+ else {
4022
+ attrs[`block-attribute-${idx}`] = attrName;
4023
+ }
4021
4024
  }
4022
4025
  }
4023
4026
  else if (this.translatableAttributes.includes(key)) {
@@ -4054,8 +4057,8 @@ class CodeGenerator {
4054
4057
  targetExpr = compileExpr(dynamicTgExpr);
4055
4058
  }
4056
4059
  }
4057
- idx = block.insertData(`${fullExpression} === ${targetExpr}`, "attr");
4058
- attrs[`block-attribute-${idx}`] = specialInitTargetAttr;
4060
+ idx = block.insertData(`${fullExpression} === ${targetExpr}`, "prop");
4061
+ attrs[`block-property-${idx}`] = specialInitTargetAttr;
4059
4062
  }
4060
4063
  else if (hasDynamicChildren) {
4061
4064
  const bValueId = generateId("bValue");
@@ -4063,8 +4066,8 @@ class CodeGenerator {
4063
4066
  this.define(tModelSelectedExpr, fullExpression);
4064
4067
  }
4065
4068
  else {
4066
- idx = block.insertData(`${fullExpression}`, "attr");
4067
- attrs[`block-attribute-${idx}`] = targetAttr;
4069
+ idx = block.insertData(`${fullExpression}`, "prop");
4070
+ attrs[`block-property-${idx}`] = targetAttr;
4068
4071
  }
4069
4072
  this.helpers.add("toNumber");
4070
4073
  let valueCode = `ev.target.${targetAttr}`;
@@ -4082,32 +4085,21 @@ class CodeGenerator {
4082
4085
  }
4083
4086
  // t-ref
4084
4087
  if (ast.ref) {
4085
- this.target.hasRef = true;
4088
+ if (this.dev) {
4089
+ this.helpers.add("makeRefWrapper");
4090
+ this.target.hasRefWrapper = true;
4091
+ }
4086
4092
  const isDynamic = INTERP_REGEXP.test(ast.ref);
4093
+ let name = `\`${ast.ref}\``;
4087
4094
  if (isDynamic) {
4088
- this.helpers.add("singleRefSetter");
4089
- const str = replaceDynamicParts(ast.ref, (expr) => this.captureExpression(expr, true));
4090
- const idx = block.insertData(`singleRefSetter(refs, ${str})`, "ref");
4091
- attrs["block-ref"] = String(idx);
4095
+ name = replaceDynamicParts(ast.ref, (expr) => this.captureExpression(expr, true));
4092
4096
  }
4093
- else {
4094
- let name = ast.ref;
4095
- if (name in this.target.refInfo) {
4096
- // ref has already been defined
4097
- this.helpers.add("multiRefSetter");
4098
- const info = this.target.refInfo[name];
4099
- const index = block.data.push(info[0]) - 1;
4100
- attrs["block-ref"] = String(index);
4101
- info[1] = `multiRefSetter(refs, \`${name}\`)`;
4102
- }
4103
- else {
4104
- let id = generateId("ref");
4105
- this.helpers.add("singleRefSetter");
4106
- this.target.refInfo[name] = [id, `singleRefSetter(refs, \`${name}\`)`];
4107
- const index = block.data.push(id) - 1;
4108
- attrs["block-ref"] = String(index);
4109
- }
4097
+ let setRefStr = `(el) => this.__owl__.setRef((${name}), el)`;
4098
+ if (this.dev) {
4099
+ setRefStr = `refWrapper(${name}, ${setRefStr})`;
4110
4100
  }
4101
+ const idx = block.insertData(setRefStr, "ref");
4102
+ attrs["block-ref"] = String(idx);
4111
4103
  }
4112
4104
  const dom = xmlDoc.createElement(ast.tag);
4113
4105
  for (const [attr, val] of Object.entries(attrs)) {
@@ -4130,6 +4122,7 @@ class CodeGenerator {
4130
4122
  tKeyExpr: ctx.tKeyExpr,
4131
4123
  nameSpace,
4132
4124
  tModelSelectedExpr,
4125
+ inPreTag: ctx.inPreTag || ast.tag === "pre",
4133
4126
  });
4134
4127
  this.compileAST(child, subCtx);
4135
4128
  }
@@ -4514,13 +4507,15 @@ class CodeGenerator {
4514
4507
  value = this.captureExpression(value);
4515
4508
  if (name.includes(".")) {
4516
4509
  let [_name, suffix] = name.split(".");
4517
- if (suffix === "bind") {
4518
- this.helpers.add("bind");
4519
- name = _name;
4520
- value = `bind(this, ${value || undefined})`;
4521
- }
4522
- else {
4523
- throw new OwlError("Invalid prop suffix");
4510
+ name = _name;
4511
+ switch (suffix) {
4512
+ case "bind":
4513
+ value = `${value}.bind(this)`;
4514
+ break;
4515
+ case "alike":
4516
+ break;
4517
+ default:
4518
+ throw new OwlError("Invalid prop suffix");
4524
4519
  }
4525
4520
  }
4526
4521
  name = /^[a-z_]+$/i.test(name) ? name : `'${name}'`;
@@ -4607,9 +4602,16 @@ class CodeGenerator {
4607
4602
  keyArg = `${ctx.tKeyExpr} + ${keyArg}`;
4608
4603
  }
4609
4604
  let id = generateId("comp");
4605
+ const propList = [];
4606
+ for (let p in ast.props || {}) {
4607
+ let [name, suffix] = p.split(".");
4608
+ if (!suffix) {
4609
+ propList.push(`"${name}"`);
4610
+ }
4611
+ }
4610
4612
  this.staticDefs.push({
4611
4613
  id,
4612
- expr: `app.createComponent(${ast.isDynamic ? null : expr}, ${!ast.isDynamic}, ${!!ast.slots}, ${!!ast.dynamicProps}, ${!ast.props && !ast.dynamicProps})`,
4614
+ expr: `app.createComponent(${ast.isDynamic ? null : expr}, ${!ast.isDynamic}, ${!!ast.slots}, ${!!ast.dynamicProps}, [${propList}])`,
4613
4615
  });
4614
4616
  if (ast.isDynamic) {
4615
4617
  // If the component class changes, this can cause delayed renders to go
@@ -4787,15 +4789,11 @@ function parseTNode(node, ctx) {
4787
4789
  // Text and Comment Nodes
4788
4790
  // -----------------------------------------------------------------------------
4789
4791
  const lineBreakRE = /[\r\n]/;
4790
- const whitespaceRE = /\s+/g;
4791
4792
  function parseTextCommentNode(node, ctx) {
4792
4793
  if (node.nodeType === Node.TEXT_NODE) {
4793
4794
  let value = node.textContent || "";
4794
- if (!ctx.inPreTag) {
4795
- if (lineBreakRE.test(value) && !value.trim()) {
4796
- return null;
4797
- }
4798
- value = value.replace(whitespaceRE, " ");
4795
+ if (!ctx.inPreTag && lineBreakRE.test(value) && !value.trim()) {
4796
+ return null;
4799
4797
  }
4800
4798
  return { type: 0 /* Text */, value };
4801
4799
  }
@@ -5483,50 +5481,8 @@ function compile(template, options = {}) {
5483
5481
  return new Function("app, bdom, helpers", code);
5484
5482
  }
5485
5483
 
5486
- const mainEventHandler = (data, ev, currentTarget) => {
5487
- const { data: _data, modifiers } = filterOutModifiersFromData(data);
5488
- data = _data;
5489
- let stopped = false;
5490
- if (modifiers.length) {
5491
- let selfMode = false;
5492
- const isSelf = ev.target === currentTarget;
5493
- for (const mod of modifiers) {
5494
- switch (mod) {
5495
- case "self":
5496
- selfMode = true;
5497
- if (isSelf) {
5498
- continue;
5499
- }
5500
- else {
5501
- return stopped;
5502
- }
5503
- case "prevent":
5504
- if ((selfMode && isSelf) || !selfMode)
5505
- ev.preventDefault();
5506
- continue;
5507
- case "stop":
5508
- if ((selfMode && isSelf) || !selfMode)
5509
- ev.stopPropagation();
5510
- stopped = true;
5511
- continue;
5512
- }
5513
- }
5514
- }
5515
- // If handler is empty, the array slot 0 will also be empty, and data will not have the property 0
5516
- // We check this rather than data[0] being truthy (or typeof function) so that it crashes
5517
- // as expected when there is a handler expression that evaluates to a falsy value
5518
- if (Object.hasOwnProperty.call(data, 0)) {
5519
- const handler = data[0];
5520
- if (typeof handler !== "function") {
5521
- throw new OwlError(`Invalid handler (expected a function, received: '${handler}')`);
5522
- }
5523
- let node = data[1] ? data[1].__owl__ : null;
5524
- if (node ? node.status === 1 /* MOUNTED */ : true) {
5525
- handler.call(node ? node.component : null, ev);
5526
- }
5527
- }
5528
- return stopped;
5529
- };
5484
+ // do not modify manually. This value is updated by the release script.
5485
+ const version = "2.0.8";
5530
5486
 
5531
5487
  // -----------------------------------------------------------------------------
5532
5488
  // Scheduler
@@ -5611,6 +5567,7 @@ class App extends TemplateSet {
5611
5567
  super(config);
5612
5568
  this.scheduler = new Scheduler();
5613
5569
  this.root = null;
5570
+ this.name = config.name || "";
5614
5571
  this.Root = Root;
5615
5572
  window.__OWL_DEVTOOLS__.apps.add(this);
5616
5573
  if (config.test) {
@@ -5671,21 +5628,36 @@ class App extends TemplateSet {
5671
5628
  }
5672
5629
  window.__OWL_DEVTOOLS__.apps.delete(this);
5673
5630
  }
5674
- createComponent(name, isStatic, hasSlotsProp, hasDynamicPropList, hasNoProp) {
5631
+ createComponent(name, isStatic, hasSlotsProp, hasDynamicPropList, propList) {
5675
5632
  const isDynamic = !isStatic;
5676
- function _arePropsDifferent(props1, props2) {
5677
- for (let k in props1) {
5678
- if (props1[k] !== props2[k]) {
5679
- return true;
5633
+ let arePropsDifferent;
5634
+ const hasNoProp = propList.length === 0;
5635
+ if (hasSlotsProp) {
5636
+ arePropsDifferent = (_1, _2) => true;
5637
+ }
5638
+ else if (hasDynamicPropList) {
5639
+ arePropsDifferent = function (props1, props2) {
5640
+ for (let k in props1) {
5641
+ if (props1[k] !== props2[k]) {
5642
+ return true;
5643
+ }
5680
5644
  }
5681
- }
5682
- return hasDynamicPropList && Object.keys(props1).length !== Object.keys(props2).length;
5645
+ return Object.keys(props1).length !== Object.keys(props2).length;
5646
+ };
5647
+ }
5648
+ else if (hasNoProp) {
5649
+ arePropsDifferent = (_1, _2) => false;
5650
+ }
5651
+ else {
5652
+ arePropsDifferent = function (props1, props2) {
5653
+ for (let p of propList) {
5654
+ if (props1[p] !== props2[p]) {
5655
+ return true;
5656
+ }
5657
+ }
5658
+ return false;
5659
+ };
5683
5660
  }
5684
- const arePropsDifferent = hasSlotsProp
5685
- ? (_1, _2) => true
5686
- : hasNoProp
5687
- ? (_1, _2) => false
5688
- : _arePropsDifferent;
5689
5661
  const updateAndRender = ComponentNode.prototype.updateAndRender;
5690
5662
  const initiateRender = ComponentNode.prototype.initiateRender;
5691
5663
  return (props, key, ctx, parent, C) => {
@@ -5729,10 +5701,56 @@ class App extends TemplateSet {
5729
5701
  }
5730
5702
  }
5731
5703
  App.validateTarget = validateTarget;
5704
+ App.version = version;
5732
5705
  async function mount(C, target, config = {}) {
5733
5706
  return new App(C, config).mount(target, config);
5734
5707
  }
5735
5708
 
5709
+ const mainEventHandler = (data, ev, currentTarget) => {
5710
+ const { data: _data, modifiers } = filterOutModifiersFromData(data);
5711
+ data = _data;
5712
+ let stopped = false;
5713
+ if (modifiers.length) {
5714
+ let selfMode = false;
5715
+ const isSelf = ev.target === currentTarget;
5716
+ for (const mod of modifiers) {
5717
+ switch (mod) {
5718
+ case "self":
5719
+ selfMode = true;
5720
+ if (isSelf) {
5721
+ continue;
5722
+ }
5723
+ else {
5724
+ return stopped;
5725
+ }
5726
+ case "prevent":
5727
+ if ((selfMode && isSelf) || !selfMode)
5728
+ ev.preventDefault();
5729
+ continue;
5730
+ case "stop":
5731
+ if ((selfMode && isSelf) || !selfMode)
5732
+ ev.stopPropagation();
5733
+ stopped = true;
5734
+ continue;
5735
+ }
5736
+ }
5737
+ }
5738
+ // If handler is empty, the array slot 0 will also be empty, and data will not have the property 0
5739
+ // We check this rather than data[0] being truthy (or typeof function) so that it crashes
5740
+ // as expected when there is a handler expression that evaluates to a falsy value
5741
+ if (Object.hasOwnProperty.call(data, 0)) {
5742
+ const handler = data[0];
5743
+ if (typeof handler !== "function") {
5744
+ throw new OwlError(`Invalid handler (expected a function, received: '${handler}')`);
5745
+ }
5746
+ let node = data[1] ? data[1].__owl__ : null;
5747
+ if (node ? node.status === 1 /* MOUNTED */ : true) {
5748
+ handler.call(node ? node.component : null, ev);
5749
+ }
5750
+ }
5751
+ return stopped;
5752
+ };
5753
+
5736
5754
  function status(component) {
5737
5755
  switch (component.__owl__.status) {
5738
5756
  case 0 /* NEW */:
@@ -5756,7 +5774,8 @@ function useRef(name) {
5756
5774
  const refs = node.refs;
5757
5775
  return {
5758
5776
  get el() {
5759
- return refs[name] || null;
5777
+ const el = refs[name];
5778
+ return (el === null || el === void 0 ? void 0 : el.ownerDocument.contains(el)) ? el : null;
5760
5779
  },
5761
5780
  };
5762
5781
  }
@@ -5861,7 +5880,9 @@ const blockDom = {
5861
5880
  html,
5862
5881
  comment,
5863
5882
  };
5864
- const __info__ = {};
5883
+ const __info__ = {
5884
+ version: App.version,
5885
+ };
5865
5886
 
5866
5887
  TemplateSet.prototype._compileTemplate = function _compileTemplate(name, template) {
5867
5888
  return compile(template, {
@@ -5908,7 +5929,6 @@ exports.whenReady = whenReady;
5908
5929
  exports.xml = xml;
5909
5930
 
5910
5931
 
5911
- __info__.version = '2.0.7';
5912
- __info__.date = '2023-02-20T08:44:48.289Z';
5913
- __info__.hash = '276c8a0';
5932
+ __info__.date = '2023-03-09T12:11:34.048Z';
5933
+ __info__.hash = '532ab7f';
5914
5934
  __info__.url = 'https://github.com/odoo/owl';