@odoo/owl 3.0.0-alpha.22 → 3.0.0-alpha.23

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
@@ -2003,51 +2003,11 @@
2003
2003
  // Maps fibers to thrown errors
2004
2004
  const fibersInError = new WeakMap();
2005
2005
  const nodeErrorHandlers = new WeakMap();
2006
- function destroyApp(app, error) {
2007
- try {
2008
- app.destroy();
2009
- }
2010
- catch (e) {
2011
- // mute all errors here because we are in a corrupted state anyway
2012
- }
2013
- const e = Object.assign(new OwlError(`[Owl] Unhandled error. Destroying the root component`), {
2014
- cause: error,
2015
- });
2016
- return e;
2017
- }
2018
- function _handleError(node, error) {
2019
- if (!node) {
2020
- return false;
2021
- }
2022
- const fiber = node.fiber;
2023
- if (fiber) {
2024
- fibersInError.set(fiber, error);
2025
- }
2026
- const errorHandlers = nodeErrorHandlers.get(node);
2027
- if (errorHandlers) {
2028
- let handled = false;
2029
- // execute in the opposite order
2030
- const finalize = () => destroyApp(node.app, error);
2031
- for (let i = errorHandlers.length - 1; i >= 0; i--) {
2032
- try {
2033
- errorHandlers[i](error, finalize);
2034
- handled = true;
2035
- break;
2036
- }
2037
- catch (e) {
2038
- error = e;
2039
- }
2040
- }
2041
- if (handled) {
2042
- return true;
2043
- }
2044
- }
2045
- return _handleError(node.parent, error);
2046
- }
2047
2006
  function handleError(params) {
2048
2007
  let { error } = params;
2049
- const node = "node" in params ? params.node : params.fiber.node;
2008
+ let node = "node" in params ? params.node : params.fiber.node;
2050
2009
  const fiber = "fiber" in params ? params.fiber : node.fiber;
2010
+ const app = node.app;
2051
2011
  if (fiber) {
2052
2012
  // resets the fibers on components if possible. This is important so that
2053
2013
  // new renderings can be properly included in the initial one, if any.
@@ -2059,10 +2019,43 @@
2059
2019
  } while (current);
2060
2020
  fibersInError.set(fiber.root, error);
2061
2021
  }
2062
- const handled = _handleError(node, error);
2063
- if (!handled) {
2064
- throw destroyApp(node.app, error);
2022
+ const finalize = () => {
2023
+ try {
2024
+ app.destroy();
2025
+ }
2026
+ catch (e) {
2027
+ // mute all errors here because we are in a corrupted state anyway
2028
+ }
2029
+ return Object.assign(new OwlError(`[Owl] Unhandled error. Destroying the root component`), {
2030
+ cause: error,
2031
+ });
2032
+ };
2033
+ // Walk up the component tree looking for error handlers
2034
+ while (node) {
2035
+ const nodeFiber = node.fiber;
2036
+ if (nodeFiber) {
2037
+ fibersInError.set(nodeFiber, error);
2038
+ }
2039
+ const errorHandlers = nodeErrorHandlers.get(node);
2040
+ if (errorHandlers) {
2041
+ // execute in the opposite order
2042
+ for (let i = errorHandlers.length - 1; i >= 0; i--) {
2043
+ try {
2044
+ errorHandlers[i](error, finalize);
2045
+ return; // handled
2046
+ }
2047
+ catch (e) {
2048
+ error = e;
2049
+ }
2050
+ }
2051
+ }
2052
+ node = node.parent;
2065
2053
  }
2054
+ // No handler found — create the OwlError, then let the app handle it.
2055
+ // app._handleError is called after error creation, so it doesn't appear
2056
+ // in the error's .stack property.
2057
+ const owlError = finalize();
2058
+ app._handleError(owlError);
2066
2059
  }
2067
2060
 
2068
2061
  function makeChildFiber(node, parent) {
@@ -2198,7 +2191,7 @@
2198
2191
  this.bdom = node.renderFn();
2199
2192
  }
2200
2193
  catch (e) {
2201
- node.app.handleError({ node, error: e });
2194
+ handleError({ node, error: e });
2202
2195
  }
2203
2196
  setComputation(c);
2204
2197
  root.setCounter(root.counter - 1);
@@ -2268,7 +2261,7 @@
2268
2261
  fiber.node.willUnmount = [];
2269
2262
  }
2270
2263
  this.locked = false;
2271
- node.app.handleError({ fiber: current || this, error: e });
2264
+ handleError({ fiber: current || this, error: e });
2272
2265
  }
2273
2266
  }
2274
2267
  setCounter(newValue) {
@@ -2324,7 +2317,7 @@
2324
2317
  }
2325
2318
  }
2326
2319
  catch (e) {
2327
- this.node.app.handleError({ fiber: current, error: e });
2320
+ handleError({ fiber: current, error: e });
2328
2321
  }
2329
2322
  }
2330
2323
  }
@@ -2402,7 +2395,7 @@
2402
2395
  await Promise.all(promises);
2403
2396
  }
2404
2397
  catch (e) {
2405
- this.app.handleError({ node: this, error: e });
2398
+ handleError({ node: this, error: e });
2406
2399
  return;
2407
2400
  }
2408
2401
  if (this.status === 0 /* STATUS.NEW */ && this.fiber === fiber) {
@@ -2492,7 +2485,7 @@
2492
2485
  }
2493
2486
  }
2494
2487
  catch (e) {
2495
- this.app.handleError({ error: e, node: this });
2488
+ handleError({ error: e, node: this });
2496
2489
  }
2497
2490
  }
2498
2491
  for (const computation of this.computations) {
@@ -5675,7 +5668,7 @@
5675
5668
  }
5676
5669
 
5677
5670
  // do not modify manually. This file is generated by the release script.
5678
- const version = "3.0.0-alpha.22";
5671
+ const version = "3.0.0-alpha.23";
5679
5672
 
5680
5673
  function effect(fn) {
5681
5674
  const computation = createComputation(() => {
@@ -5873,8 +5866,33 @@
5873
5866
  node._destroy();
5874
5867
  }
5875
5868
  this.cancelledNodes.clear();
5876
- for (let task of this.tasks) {
5877
- this.processFiber(task);
5869
+ for (let fiber of this.tasks) {
5870
+ if (fiber.root !== fiber) {
5871
+ this.tasks.delete(fiber);
5872
+ continue;
5873
+ }
5874
+ const hasError = fibersInError.has(fiber);
5875
+ if (hasError && fiber.counter !== 0) {
5876
+ this.tasks.delete(fiber);
5877
+ continue;
5878
+ }
5879
+ if (fiber.node.status === 3 /* STATUS.DESTROYED */) {
5880
+ this.tasks.delete(fiber);
5881
+ continue;
5882
+ }
5883
+ if (fiber.counter === 0) {
5884
+ if (!hasError) {
5885
+ fiber.complete();
5886
+ }
5887
+ // at this point, the fiber should have been applied to the DOM, so we can
5888
+ // remove it from the task list. If it is not the case, it means that there
5889
+ // was an error and an error handler triggered a new rendering that recycled
5890
+ // the fiber, so in that case, we actually want to keep the fiber around,
5891
+ // otherwise it will just be ignored.
5892
+ if (fiber.appliedToDom) {
5893
+ this.tasks.delete(fiber);
5894
+ }
5895
+ }
5878
5896
  }
5879
5897
  for (let task of this.tasks) {
5880
5898
  if (task.node.status === 3 /* STATUS.DESTROYED */) {
@@ -5883,34 +5901,6 @@
5883
5901
  }
5884
5902
  this.processing = false;
5885
5903
  }
5886
- processFiber(fiber) {
5887
- if (fiber.root !== fiber) {
5888
- this.tasks.delete(fiber);
5889
- return;
5890
- }
5891
- const hasError = fibersInError.has(fiber);
5892
- if (hasError && fiber.counter !== 0) {
5893
- this.tasks.delete(fiber);
5894
- return;
5895
- }
5896
- if (fiber.node.status === 3 /* STATUS.DESTROYED */) {
5897
- this.tasks.delete(fiber);
5898
- return;
5899
- }
5900
- if (fiber.counter === 0) {
5901
- if (!hasError) {
5902
- fiber.complete();
5903
- }
5904
- // at this point, the fiber should have been applied to the DOM, so we can
5905
- // remove it from the task list. If it is not the case, it means that there
5906
- // was an error and an error handler triggered a new rendering that recycled
5907
- // the fiber, so in that case, we actually want to keep the fiber around,
5908
- // otherwise it will just be ignored.
5909
- if (fiber.appliedToDom) {
5910
- this.tasks.delete(fiber);
5911
- }
5912
- }
5913
- }
5914
5904
  }
5915
5905
 
5916
5906
  let hasBeenLogged = false;
@@ -6010,8 +6000,8 @@
6010
6000
  this.scheduler.processTasks();
6011
6001
  apps.delete(this);
6012
6002
  }
6013
- handleError(...args) {
6014
- return handleError(...args);
6003
+ _handleError(error) {
6004
+ throw error;
6015
6005
  }
6016
6006
  }
6017
6007
  async function mount(C, target, config = {}) {
@@ -6069,14 +6059,20 @@
6069
6059
  // hooks
6070
6060
  // -----------------------------------------------------------------------------
6071
6061
  function decorate(node, f, hookName) {
6072
- const result = f.bind(node.component);
6073
6062
  if (node.app.dev) {
6074
- const suffix = f.name ? ` <${f.name}>` : "";
6075
- Reflect.defineProperty(result, "name", {
6076
- value: hookName + suffix,
6077
- });
6063
+ const component = node.component;
6064
+ const componentName = component ? component.constructor.name : "Component";
6065
+ const name = `${componentName}.${hookName}`;
6066
+ // Create a named wrapper so the name appears in stack traces.
6067
+ // V8 uses computed property keys as inferred function names.
6068
+ const wrapper = {
6069
+ [name]() {
6070
+ return f.call(component);
6071
+ },
6072
+ };
6073
+ return wrapper[name];
6078
6074
  }
6079
- return result;
6075
+ return f.bind(node.component);
6080
6076
  }
6081
6077
  function onWillStart(fn) {
6082
6078
  const { node } = getContext("component");
@@ -6334,22 +6330,30 @@
6334
6330
  }
6335
6331
  }
6336
6332
 
6337
- const anyType = function validateAny() { };
6338
- const booleanType = function validateBoolean(context) {
6339
- if (typeof context.value !== "boolean") {
6340
- context.addIssue({ message: "value is not a boolean" });
6341
- }
6342
- };
6343
- const numberType = function validateNumber(context) {
6344
- if (typeof context.value !== "number") {
6345
- context.addIssue({ message: "value is not a number" });
6346
- }
6347
- };
6348
- const stringType = function validateString(context) {
6349
- if (typeof context.value !== "string") {
6350
- context.addIssue({ message: "value is not a string" });
6351
- }
6352
- };
6333
+ function anyType() {
6334
+ return function validateAny() { };
6335
+ }
6336
+ function booleanType() {
6337
+ return function validateBoolean(context) {
6338
+ if (typeof context.value !== "boolean") {
6339
+ context.addIssue({ message: "value is not a boolean" });
6340
+ }
6341
+ };
6342
+ }
6343
+ function numberType() {
6344
+ return function validateNumber(context) {
6345
+ if (typeof context.value !== "number") {
6346
+ context.addIssue({ message: "value is not a number" });
6347
+ }
6348
+ };
6349
+ }
6350
+ function stringType() {
6351
+ return function validateString(context) {
6352
+ if (typeof context.value !== "string") {
6353
+ context.addIssue({ message: "value is not a string" });
6354
+ }
6355
+ };
6356
+ }
6353
6357
  function arrayType(elementType) {
6354
6358
  return function validateArray(context) {
6355
6359
  if (!Array.isArray(context.value)) {
@@ -6540,6 +6544,9 @@
6540
6544
  }
6541
6545
  };
6542
6546
  }
6547
+ function componentType() {
6548
+ return constructorType(Component);
6549
+ }
6543
6550
  function ref(type) {
6544
6551
  return union([literalType(null), instanceType(type)]);
6545
6552
  }
@@ -6548,6 +6555,7 @@
6548
6555
  any: anyType,
6549
6556
  array: arrayType,
6550
6557
  boolean: booleanType,
6558
+ component: componentType,
6551
6559
  constructor: constructorType,
6552
6560
  customValidator: customValidator,
6553
6561
  function: functionType,
@@ -6816,8 +6824,8 @@
6816
6824
  exports.xml = xml;
6817
6825
 
6818
6826
 
6819
- __info__.date = '2026-04-08T13:31:02.500Z';
6820
- __info__.hash = '2e9164e';
6827
+ __info__.date = '2026-04-10T07:28:23.029Z';
6828
+ __info__.hash = 'e5e6d92';
6821
6829
  __info__.url = 'https://github.com/odoo/owl';
6822
6830
 
6823
6831