@odoo/owl 2.0.0-beta-14 → 2.0.0-beta-15

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
@@ -81,6 +81,68 @@ function toggler(key, child) {
81
81
  return new VToggler(key, child);
82
82
  }
83
83
 
84
+ // Custom error class that wraps error that happen in the owl lifecycle
85
+ class OwlError extends Error {
86
+ }
87
+ // Maps fibers to thrown errors
88
+ const fibersInError = new WeakMap();
89
+ const nodeErrorHandlers = new WeakMap();
90
+ function _handleError(node, error) {
91
+ if (!node) {
92
+ return false;
93
+ }
94
+ const fiber = node.fiber;
95
+ if (fiber) {
96
+ fibersInError.set(fiber, error);
97
+ }
98
+ const errorHandlers = nodeErrorHandlers.get(node);
99
+ if (errorHandlers) {
100
+ let handled = false;
101
+ // execute in the opposite order
102
+ for (let i = errorHandlers.length - 1; i >= 0; i--) {
103
+ try {
104
+ errorHandlers[i](error);
105
+ handled = true;
106
+ break;
107
+ }
108
+ catch (e) {
109
+ error = e;
110
+ }
111
+ }
112
+ if (handled) {
113
+ return true;
114
+ }
115
+ }
116
+ return _handleError(node.parent, error);
117
+ }
118
+ function handleError(params) {
119
+ let { error } = params;
120
+ // Wrap error if it wasn't wrapped by wrapError (ie when not in dev mode)
121
+ if (!(error instanceof OwlError)) {
122
+ error = Object.assign(new OwlError("An error occured in the owl lifecycle"), { cause: error });
123
+ }
124
+ const node = "node" in params ? params.node : params.fiber.node;
125
+ const fiber = "fiber" in params ? params.fiber : node.fiber;
126
+ // resets the fibers on components if possible. This is important so that
127
+ // new renderings can be properly included in the initial one, if any.
128
+ let current = fiber;
129
+ do {
130
+ current.node.fiber = current;
131
+ current = current.parent;
132
+ } while (current);
133
+ fibersInError.set(fiber.root, error);
134
+ const handled = _handleError(node, error);
135
+ if (!handled) {
136
+ console.warn(`[Owl] Unhandled error. Destroying the root component`);
137
+ try {
138
+ node.app.destroy();
139
+ }
140
+ catch (e) {
141
+ console.error(e);
142
+ }
143
+ }
144
+ }
145
+
84
146
  const { setAttribute: elemSetAttribute, removeAttribute } = Element.prototype;
85
147
  const tokenList = DOMTokenList.prototype;
86
148
  const tokenListAdd = tokenList.add;
@@ -702,7 +764,7 @@ function buildTree(node, parent = null, domParentTree = null) {
702
764
  };
703
765
  }
704
766
  }
705
- throw new Error("boom");
767
+ throw new OwlError("boom");
706
768
  }
707
769
  function addRef(tree) {
708
770
  tree.isRef = true;
@@ -1386,61 +1448,6 @@ function remove(vnode, withBeforeRemove = false) {
1386
1448
  vnode.remove();
1387
1449
  }
1388
1450
 
1389
- // Maps fibers to thrown errors
1390
- const fibersInError = new WeakMap();
1391
- const nodeErrorHandlers = new WeakMap();
1392
- function _handleError(node, error) {
1393
- if (!node) {
1394
- return false;
1395
- }
1396
- const fiber = node.fiber;
1397
- if (fiber) {
1398
- fibersInError.set(fiber, error);
1399
- }
1400
- const errorHandlers = nodeErrorHandlers.get(node);
1401
- if (errorHandlers) {
1402
- let handled = false;
1403
- // execute in the opposite order
1404
- for (let i = errorHandlers.length - 1; i >= 0; i--) {
1405
- try {
1406
- errorHandlers[i](error);
1407
- handled = true;
1408
- break;
1409
- }
1410
- catch (e) {
1411
- error = e;
1412
- }
1413
- }
1414
- if (handled) {
1415
- return true;
1416
- }
1417
- }
1418
- return _handleError(node.parent, error);
1419
- }
1420
- function handleError(params) {
1421
- const error = params.error;
1422
- const node = "node" in params ? params.node : params.fiber.node;
1423
- const fiber = "fiber" in params ? params.fiber : node.fiber;
1424
- // resets the fibers on components if possible. This is important so that
1425
- // new renderings can be properly included in the initial one, if any.
1426
- let current = fiber;
1427
- do {
1428
- current.node.fiber = current;
1429
- current = current.parent;
1430
- } while (current);
1431
- fibersInError.set(fiber.root, error);
1432
- const handled = _handleError(node, error);
1433
- if (!handled) {
1434
- console.warn(`[Owl] Unhandled error. Destroying the root component`);
1435
- try {
1436
- node.app.destroy();
1437
- }
1438
- catch (e) {
1439
- console.error(e);
1440
- }
1441
- }
1442
- }
1443
-
1444
1451
  function makeChildFiber(node, parent) {
1445
1452
  let current = node.fiber;
1446
1453
  if (current) {
@@ -1479,7 +1486,7 @@ function makeRootFiber(node) {
1479
1486
  return fiber;
1480
1487
  }
1481
1488
  function throwOnRender() {
1482
- throw new Error("Attempted to render cancelled fiber");
1489
+ throw new OwlError("Attempted to render cancelled fiber");
1483
1490
  }
1484
1491
  /**
1485
1492
  * @returns number of not-yet rendered fibers cancelled
@@ -1856,7 +1863,7 @@ const reactiveCache = new WeakMap();
1856
1863
  */
1857
1864
  function reactive(target, callback = () => { }) {
1858
1865
  if (!canBeMadeReactive(target)) {
1859
- throw new Error(`Cannot make the given value reactive`);
1866
+ throw new OwlError(`Cannot make the given value reactive`);
1860
1867
  }
1861
1868
  if (SKIP in target) {
1862
1869
  return target;
@@ -2125,10 +2132,10 @@ function batched(callback) {
2125
2132
  }
2126
2133
  function validateTarget(target) {
2127
2134
  if (!(target instanceof HTMLElement)) {
2128
- throw new Error("Cannot mount component: the target is not a valid DOM element");
2135
+ throw new OwlError("Cannot mount component: the target is not a valid DOM element");
2129
2136
  }
2130
2137
  if (!document.body.contains(target)) {
2131
- throw new Error("Cannot mount a component on a detached dom node");
2138
+ throw new OwlError("Cannot mount a component on a detached dom node");
2132
2139
  }
2133
2140
  }
2134
2141
  class EventBus extends EventTarget {
@@ -2149,7 +2156,7 @@ function whenReady(fn) {
2149
2156
  async function loadFile(url) {
2150
2157
  const result = await fetch(url);
2151
2158
  if (!result.ok) {
2152
- throw new Error("Error while fetching xml templates");
2159
+ throw new OwlError("Error while fetching xml templates");
2153
2160
  }
2154
2161
  return await result.text();
2155
2162
  }
@@ -2171,7 +2178,7 @@ function markup(value) {
2171
2178
  let currentNode = null;
2172
2179
  function getCurrent() {
2173
2180
  if (!currentNode) {
2174
- throw new Error("No active component (a hook function should only be called in 'setup')");
2181
+ throw new OwlError("No active component (a hook function should only be called in 'setup')");
2175
2182
  }
2176
2183
  return currentNode;
2177
2184
  }
@@ -2233,7 +2240,6 @@ class ComponentNode {
2233
2240
  this.parent = parent;
2234
2241
  this.props = props;
2235
2242
  this.parentKey = parentKey;
2236
- this.level = parent ? parent.level + 1 : 0;
2237
2243
  const defaultProps = C.defaultProps;
2238
2244
  props = Object.assign({}, props);
2239
2245
  if (defaultProps) {
@@ -2466,17 +2472,24 @@ class ComponentNode {
2466
2472
 
2467
2473
  const TIMEOUT = Symbol("timeout");
2468
2474
  function wrapError(fn, hookName) {
2469
- const error = new Error(`The following error occurred in ${hookName}: `);
2470
- const timeoutError = new Error(`${hookName}'s promise hasn't resolved after 3 seconds`);
2475
+ const error = new OwlError(`The following error occurred in ${hookName}: `);
2476
+ const timeoutError = new OwlError(`${hookName}'s promise hasn't resolved after 3 seconds`);
2471
2477
  const node = getCurrent();
2472
2478
  return (...args) => {
2479
+ const onError = (cause) => {
2480
+ if (cause instanceof Error) {
2481
+ error.cause = cause;
2482
+ error.message += `"${cause.message}"`;
2483
+ }
2484
+ throw error;
2485
+ };
2473
2486
  try {
2474
2487
  const result = fn(...args);
2475
2488
  if (result instanceof Promise) {
2476
2489
  if (hookName === "onWillStart" || hookName === "onWillUpdateProps") {
2477
2490
  const fiber = node.fiber;
2478
2491
  Promise.race([
2479
- result,
2492
+ result.catch(() => { }),
2480
2493
  new Promise((resolve) => setTimeout(() => resolve(TIMEOUT), 3000)),
2481
2494
  ]).then((res) => {
2482
2495
  if (res === TIMEOUT && node.fiber === fiber) {
@@ -2484,21 +2497,12 @@ function wrapError(fn, hookName) {
2484
2497
  }
2485
2498
  });
2486
2499
  }
2487
- return result.catch((cause) => {
2488
- error.cause = cause;
2489
- if (cause instanceof Error) {
2490
- error.message += `"${cause.message}"`;
2491
- }
2492
- throw error;
2493
- });
2500
+ return result.catch(onError);
2494
2501
  }
2495
2502
  return result;
2496
2503
  }
2497
2504
  catch (cause) {
2498
- if (cause instanceof Error) {
2499
- error.message += `"${cause.message}"`;
2500
- }
2501
- throw error;
2505
+ onError(cause);
2502
2506
  }
2503
2507
  };
2504
2508
  }
@@ -2602,7 +2606,7 @@ class VPortal extends VText {
2602
2606
  }
2603
2607
  this.target = el && el.querySelector(this.selector);
2604
2608
  if (!this.target) {
2605
- throw new Error("invalid portal target");
2609
+ throw new OwlError("invalid portal target");
2606
2610
  }
2607
2611
  }
2608
2612
  this.realBDom.mount(this.target, null);
@@ -2696,7 +2700,7 @@ function toSchema(spec) {
2696
2700
  function validate(obj, spec) {
2697
2701
  let errors = validateSchema(obj, spec);
2698
2702
  if (errors.length) {
2699
- throw new Error("Invalid object: " + errors.join(", "));
2703
+ throw new OwlError("Invalid object: " + errors.join(", "));
2700
2704
  }
2701
2705
  }
2702
2706
  /**
@@ -2849,7 +2853,7 @@ function prepareList(collection) {
2849
2853
  keys = Object.values(collection);
2850
2854
  }
2851
2855
  else {
2852
- throw new Error("Invalid loop expression");
2856
+ throw new OwlError("Invalid loop expression");
2853
2857
  }
2854
2858
  const n = values.length;
2855
2859
  return [keys, values, n, new Array(n)];
@@ -2955,7 +2959,7 @@ function multiRefSetter(refs, name) {
2955
2959
  if (el) {
2956
2960
  count++;
2957
2961
  if (count > 1) {
2958
- throw new Error("Cannot have 2 elements with same ref name at the same time");
2962
+ throw new OwlError("Cannot have 2 elements with same ref name at the same time");
2959
2963
  }
2960
2964
  }
2961
2965
  if (count === 0 || el) {
@@ -2992,13 +2996,13 @@ function validateProps(name, props, parent) {
2992
2996
  : name in schema && !("*" in schema) && !isOptional(schema[name]);
2993
2997
  for (let p in defaultProps) {
2994
2998
  if (isMandatory(p)) {
2995
- throw new Error(`A default value cannot be defined for a mandatory prop (name: '${p}', component: ${ComponentClass.name})`);
2999
+ throw new OwlError(`A default value cannot be defined for a mandatory prop (name: '${p}', component: ${ComponentClass.name})`);
2996
3000
  }
2997
3001
  }
2998
3002
  }
2999
3003
  const errors = validateSchema(props, schema);
3000
3004
  if (errors.length) {
3001
- throw new Error(`Invalid props for component '${ComponentClass.name}': ` + errors.join(", "));
3005
+ throw new OwlError(`Invalid props for component '${ComponentClass.name}': ` + errors.join(", "));
3002
3006
  }
3003
3007
  }
3004
3008
  const helpers = {
@@ -3019,6 +3023,7 @@ const helpers = {
3019
3023
  bind,
3020
3024
  createCatcher,
3021
3025
  markRaw,
3026
+ OwlError,
3022
3027
  };
3023
3028
 
3024
3029
  const bdom = { text, createBlock, list, multi, html, toggler, comment };
@@ -3046,7 +3051,7 @@ function parseXML$1(xml) {
3046
3051
  }
3047
3052
  }
3048
3053
  }
3049
- throw new Error(msg);
3054
+ throw new OwlError(msg);
3050
3055
  }
3051
3056
  return doc;
3052
3057
  }
@@ -3077,7 +3082,7 @@ class TemplateSet {
3077
3082
  if (currentAsString === newAsString) {
3078
3083
  return;
3079
3084
  }
3080
- throw new Error(`Template ${name} already defined with different content`);
3085
+ throw new OwlError(`Template ${name} already defined with different content`);
3081
3086
  }
3082
3087
  this.rawTemplates[name] = template;
3083
3088
  }
@@ -3102,7 +3107,7 @@ class TemplateSet {
3102
3107
  extraInfo = ` (for component "${componentName}")`;
3103
3108
  }
3104
3109
  catch { }
3105
- throw new Error(`Missing template: "${name}"${extraInfo}`);
3110
+ throw new OwlError(`Missing template: "${name}"${extraInfo}`);
3106
3111
  }
3107
3112
  const isFn = typeof rawTemplate === "function" && !(rawTemplate instanceof Element);
3108
3113
  const templateFn = isFn ? rawTemplate : this._compileTemplate(name, rawTemplate);
@@ -3118,7 +3123,7 @@ class TemplateSet {
3118
3123
  return this.templates[name];
3119
3124
  }
3120
3125
  _compileTemplate(name, template) {
3121
- throw new Error(`Unable to compile a template. Please use owl full build instead`);
3126
+ throw new OwlError(`Unable to compile a template. Please use owl full build instead`);
3122
3127
  }
3123
3128
  callTemplate(owner, subTemplate, ctx, parent, key) {
3124
3129
  const template = this.getTemplate(subTemplate);
@@ -3200,14 +3205,14 @@ let tokenizeString = function (expr) {
3200
3205
  i++;
3201
3206
  cur = expr[i];
3202
3207
  if (!cur) {
3203
- throw new Error("Invalid expression");
3208
+ throw new OwlError("Invalid expression");
3204
3209
  }
3205
3210
  s += cur;
3206
3211
  }
3207
3212
  i++;
3208
3213
  }
3209
3214
  if (expr[i] !== start) {
3210
- throw new Error("Invalid expression");
3215
+ throw new OwlError("Invalid expression");
3211
3216
  }
3212
3217
  s += start;
3213
3218
  if (start === "`") {
@@ -3314,7 +3319,7 @@ function tokenize(expr) {
3314
3319
  error = e; // Silence all errors and throw a generic error below
3315
3320
  }
3316
3321
  if (current.length || error) {
3317
- throw new Error(`Tokenizer error: could not tokenize \`${expr}\``);
3322
+ throw new OwlError(`Tokenizer error: could not tokenize \`${expr}\``);
3318
3323
  }
3319
3324
  return result;
3320
3325
  }
@@ -3865,7 +3870,7 @@ class CodeGenerator {
3865
3870
  .slice(1)
3866
3871
  .map((m) => {
3867
3872
  if (!MODS.has(m)) {
3868
- throw new Error(`Unknown event modifier: '${m}'`);
3873
+ throw new OwlError(`Unknown event modifier: '${m}'`);
3869
3874
  }
3870
3875
  return `"${m}"`;
3871
3876
  });
@@ -4186,7 +4191,8 @@ class CodeGenerator {
4186
4191
  this.define(`key${this.target.loopLevel}`, ast.key ? compileExpr(ast.key) : loopVar);
4187
4192
  if (this.dev) {
4188
4193
  // Throw error on duplicate keys in dev mode
4189
- this.addLine(`if (keys${block.id}.has(key${this.target.loopLevel})) { throw new Error(\`Got duplicate key in t-foreach: \${key${this.target.loopLevel}}\`)}`);
4194
+ this.helpers.add("OwlError");
4195
+ this.addLine(`if (keys${block.id}.has(key${this.target.loopLevel})) { throw new OwlError(\`Got duplicate key in t-foreach: \${key${this.target.loopLevel}}\`)}`);
4190
4196
  this.addLine(`keys${block.id}.add(key${this.target.loopLevel});`);
4191
4197
  }
4192
4198
  let id;
@@ -4400,7 +4406,7 @@ class CodeGenerator {
4400
4406
  value = `bind(ctx, ${value || undefined})`;
4401
4407
  }
4402
4408
  else {
4403
- throw new Error("Invalid prop suffix");
4409
+ throw new OwlError("Invalid prop suffix");
4404
4410
  }
4405
4411
  }
4406
4412
  name = /^[a-z_]+$/i.test(name) ? name : `'${name}'`;
@@ -4593,9 +4599,6 @@ class CodeGenerator {
4593
4599
  }
4594
4600
  }
4595
4601
 
4596
- // -----------------------------------------------------------------------------
4597
- // AST Type definition
4598
- // -----------------------------------------------------------------------------
4599
4602
  // -----------------------------------------------------------------------------
4600
4603
  // Parser
4601
4604
  // -----------------------------------------------------------------------------
@@ -4704,7 +4707,7 @@ function parseDOMNode(node, ctx) {
4704
4707
  return null;
4705
4708
  }
4706
4709
  if (tagName.startsWith("block-")) {
4707
- throw new Error(`Invalid tag name: '${tagName}'`);
4710
+ throw new OwlError(`Invalid tag name: '${tagName}'`);
4708
4711
  }
4709
4712
  ctx = Object.assign({}, ctx);
4710
4713
  if (tagName === "pre") {
@@ -4723,14 +4726,14 @@ function parseDOMNode(node, ctx) {
4723
4726
  const value = node.getAttribute(attr);
4724
4727
  if (attr.startsWith("t-on")) {
4725
4728
  if (attr === "t-on") {
4726
- throw new Error("Missing event name with t-on directive");
4729
+ throw new OwlError("Missing event name with t-on directive");
4727
4730
  }
4728
4731
  on = on || {};
4729
4732
  on[attr.slice(5)] = value;
4730
4733
  }
4731
4734
  else if (attr.startsWith("t-model")) {
4732
4735
  if (!["input", "select", "textarea"].includes(tagName)) {
4733
- throw new Error("The t-model directive only works with <input>, <textarea> and <select>");
4736
+ throw new OwlError("The t-model directive only works with <input>, <textarea> and <select>");
4734
4737
  }
4735
4738
  let baseExpr, expr;
4736
4739
  if (hasDotAtTheEnd.test(value)) {
@@ -4744,7 +4747,7 @@ function parseDOMNode(node, ctx) {
4744
4747
  expr = value.slice(index + 1, -1);
4745
4748
  }
4746
4749
  else {
4747
- throw new Error(`Invalid t-model expression: "${value}" (it should be assignable)`);
4750
+ throw new OwlError(`Invalid t-model expression: "${value}" (it should be assignable)`);
4748
4751
  }
4749
4752
  const typeAttr = node.getAttribute("type");
4750
4753
  const isInput = tagName === "input";
@@ -4774,11 +4777,11 @@ function parseDOMNode(node, ctx) {
4774
4777
  }
4775
4778
  }
4776
4779
  else if (attr.startsWith("block-")) {
4777
- throw new Error(`Invalid attribute: '${attr}'`);
4780
+ throw new OwlError(`Invalid attribute: '${attr}'`);
4778
4781
  }
4779
4782
  else if (attr !== "t-name") {
4780
4783
  if (attr.startsWith("t-") && !attr.startsWith("t-att")) {
4781
- throw new Error(`Unknown QWeb directive: '${attr}'`);
4784
+ throw new OwlError(`Unknown QWeb directive: '${attr}'`);
4782
4785
  }
4783
4786
  const tModel = ctx.tModelInfo;
4784
4787
  if (tModel && ["t-att-value", "t-attf-value"].includes(attr)) {
@@ -4829,7 +4832,7 @@ function parseTEscNode(node, ctx) {
4829
4832
  };
4830
4833
  }
4831
4834
  if (ast.type === 11 /* TComponent */) {
4832
- throw new Error("t-esc is not supported on Component nodes");
4835
+ throw new OwlError("t-esc is not supported on Component nodes");
4833
4836
  }
4834
4837
  return tesc;
4835
4838
  }
@@ -4877,7 +4880,7 @@ function parseTForEach(node, ctx) {
4877
4880
  node.removeAttribute("t-as");
4878
4881
  const key = node.getAttribute("t-key");
4879
4882
  if (!key) {
4880
- throw new Error(`"Directive t-foreach should always be used with a t-key!" (expression: t-foreach="${collection}" t-as="${elem}")`);
4883
+ throw new OwlError(`"Directive t-foreach should always be used with a t-key!" (expression: t-foreach="${collection}" t-as="${elem}")`);
4881
4884
  }
4882
4885
  node.removeAttribute("t-key");
4883
4886
  const memo = node.getAttribute("t-memo") || "";
@@ -5037,7 +5040,7 @@ function parseComponent(node, ctx) {
5037
5040
  const firstLetter = name[0];
5038
5041
  let isDynamic = node.hasAttribute("t-component");
5039
5042
  if (isDynamic && name !== "t") {
5040
- throw new Error(`Directive 't-component' can only be used on <t> nodes (used on a <${name}>)`);
5043
+ throw new OwlError(`Directive 't-component' can only be used on <t> nodes (used on a <${name}>)`);
5041
5044
  }
5042
5045
  if (!(firstLetter === firstLetter.toUpperCase() || isDynamic)) {
5043
5046
  return null;
@@ -5061,7 +5064,7 @@ function parseComponent(node, ctx) {
5061
5064
  }
5062
5065
  else {
5063
5066
  const message = directiveErrorMap.get(name.split("-").slice(0, 2).join("-"));
5064
- throw new Error(message || `unsupported directive on Component: ${name}`);
5067
+ throw new OwlError(message || `unsupported directive on Component: ${name}`);
5065
5068
  }
5066
5069
  }
5067
5070
  else {
@@ -5076,7 +5079,7 @@ function parseComponent(node, ctx) {
5076
5079
  const slotNodes = Array.from(clone.querySelectorAll("[t-set-slot]"));
5077
5080
  for (let slotNode of slotNodes) {
5078
5081
  if (slotNode.tagName !== "t") {
5079
- throw new Error(`Directive 't-set-slot' can only be used on <t> nodes (used on a <${slotNode.tagName}>)`);
5082
+ throw new OwlError(`Directive 't-set-slot' can only be used on <t> nodes (used on a <${slotNode.tagName}>)`);
5080
5083
  }
5081
5084
  const name = slotNode.getAttribute("t-set-slot");
5082
5085
  // check if this is defined in a sub component (in which case it should
@@ -5241,25 +5244,25 @@ function normalizeTIf(el) {
5241
5244
  let nattr = (name) => +!!node.getAttribute(name);
5242
5245
  if (prevElem && (pattr("t-if") || pattr("t-elif"))) {
5243
5246
  if (pattr("t-foreach")) {
5244
- throw new Error("t-if cannot stay at the same level as t-foreach when using t-elif or t-else");
5247
+ throw new OwlError("t-if cannot stay at the same level as t-foreach when using t-elif or t-else");
5245
5248
  }
5246
5249
  if (["t-if", "t-elif", "t-else"].map(nattr).reduce(function (a, b) {
5247
5250
  return a + b;
5248
5251
  }) > 1) {
5249
- throw new Error("Only one conditional branching directive is allowed per node");
5252
+ throw new OwlError("Only one conditional branching directive is allowed per node");
5250
5253
  }
5251
5254
  // All text (with only spaces) and comment nodes (nodeType 8) between
5252
5255
  // branch nodes are removed
5253
5256
  let textNode;
5254
5257
  while ((textNode = node.previousSibling) !== prevElem) {
5255
5258
  if (textNode.nodeValue.trim().length && textNode.nodeType !== 8) {
5256
- throw new Error("text is not allowed between branching directives");
5259
+ throw new OwlError("text is not allowed between branching directives");
5257
5260
  }
5258
5261
  textNode.remove();
5259
5262
  }
5260
5263
  }
5261
5264
  else {
5262
- throw new Error("t-elif and t-else directives must be preceded by a t-if or t-elif directive");
5265
+ throw new OwlError("t-elif and t-else directives must be preceded by a t-if or t-elif directive");
5263
5266
  }
5264
5267
  }
5265
5268
  }
@@ -5275,7 +5278,7 @@ function normalizeTEsc(el) {
5275
5278
  const elements = [...el.querySelectorAll("[t-esc]")].filter((el) => el.tagName[0] === el.tagName[0].toUpperCase() || el.hasAttribute("t-component"));
5276
5279
  for (const el of elements) {
5277
5280
  if (el.childNodes.length) {
5278
- throw new Error("Cannot have t-esc on a component that already has content");
5281
+ throw new OwlError("Cannot have t-esc on a component that already has content");
5279
5282
  }
5280
5283
  const value = el.getAttribute("t-esc");
5281
5284
  el.removeAttribute("t-esc");
@@ -5327,7 +5330,7 @@ function parseXML(xml) {
5327
5330
  }
5328
5331
  }
5329
5332
  }
5330
- throw new Error(msg);
5333
+ throw new OwlError(msg);
5331
5334
  }
5332
5335
  return doc;
5333
5336
  }
@@ -5381,7 +5384,7 @@ const mainEventHandler = (data, ev, currentTarget) => {
5381
5384
  if (Object.hasOwnProperty.call(data, 0)) {
5382
5385
  const handler = data[0];
5383
5386
  if (typeof handler !== "function") {
5384
- throw new Error(`Invalid handler (expected a function, received: '${handler}')`);
5387
+ throw new OwlError(`Invalid handler (expected a function, received: '${handler}')`);
5385
5388
  }
5386
5389
  let node = data[1] ? data[1].__owl__ : null;
5387
5390
  if (node ? node.status === 1 /* MOUNTED */ : true) {
@@ -5565,10 +5568,10 @@ class App extends TemplateSet {
5565
5568
  if (isStatic) {
5566
5569
  C = parent.constructor.components[name];
5567
5570
  if (!C) {
5568
- throw new Error(`Cannot find the definition of component "${name}"`);
5571
+ throw new OwlError(`Cannot find the definition of component "${name}"`);
5569
5572
  }
5570
5573
  else if (!(C.prototype instanceof Component)) {
5571
- throw new Error(`"${name}" is not a Component. It must inherit from the Component class`);
5574
+ throw new OwlError(`"${name}" is not a Component. It must inherit from the Component class`);
5572
5575
  }
5573
5576
  }
5574
5577
  node = new ComponentNode(C, props, this, ctx, key);
@@ -5727,6 +5730,7 @@ TemplateSet.prototype._compileTemplate = function _compileTemplate(name, templat
5727
5730
  exports.App = App;
5728
5731
  exports.Component = Component;
5729
5732
  exports.EventBus = EventBus;
5733
+ exports.OwlError = OwlError;
5730
5734
  exports.__info__ = __info__;
5731
5735
  exports.blockDom = blockDom;
5732
5736
  exports.loadFile = loadFile;
@@ -5759,7 +5763,7 @@ exports.whenReady = whenReady;
5759
5763
  exports.xml = xml;
5760
5764
 
5761
5765
 
5762
- __info__.version = '2.0.0-beta-14';
5763
- __info__.date = '2022-07-08T14:17:53.900Z';
5764
- __info__.hash = 'd111845';
5766
+ __info__.version = '2.0.0-beta-15';
5767
+ __info__.date = '2022-07-20T08:02:36.538Z';
5768
+ __info__.hash = '588b655';
5765
5769
  __info__.url = 'https://github.com/odoo/owl';