@odoo/owl 3.0.0-alpha.21 → 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.
Binary file
package/dist/owl.cjs.js CHANGED
@@ -284,31 +284,6 @@ function toClassObj(expr) {
284
284
  return { [expr]: true };
285
285
  }
286
286
  }
287
- function setClass(val) {
288
- val = val === "" ? {} : toClassObj(val);
289
- // add classes
290
- const cl = this.classList;
291
- for (let c in val) {
292
- tokenListAdd.call(cl, c);
293
- }
294
- }
295
- function updateClass(val, oldVal) {
296
- oldVal = oldVal === "" ? {} : toClassObj(oldVal);
297
- val = val === "" ? {} : toClassObj(val);
298
- const cl = this.classList;
299
- // remove classes
300
- for (let c in oldVal) {
301
- if (!(c in val)) {
302
- tokenListRemove.call(cl, c);
303
- }
304
- }
305
- // add classes
306
- for (let c in val) {
307
- if (!(c in oldVal)) {
308
- tokenListAdd.call(cl, c);
309
- }
310
- }
311
- }
312
287
  // ---------------------------------------------------------------------------
313
288
  // Style
314
289
  // ---------------------------------------------------------------------------
@@ -341,7 +316,7 @@ function toStyleObj(expr) {
341
316
  }
342
317
  const prop = trim.call(part.slice(0, colonIdx));
343
318
  const value = trim.call(part.slice(colonIdx + 1));
344
- if (prop && value) {
319
+ if (prop && value && value !== "undefined") {
345
320
  result[prop] = value;
346
321
  }
347
322
  }
@@ -359,6 +334,32 @@ function toStyleObj(expr) {
359
334
  return {};
360
335
  }
361
336
  }
337
+ // ---------------------------------------------------------------------------
338
+ // Class
339
+ // ---------------------------------------------------------------------------
340
+ function setClass(val) {
341
+ val = val === "" ? {} : toClassObj(val);
342
+ for (let k in val) {
343
+ tokenListAdd.call(this.classList, k);
344
+ }
345
+ }
346
+ function updateClass(val, oldVal) {
347
+ oldVal = oldVal === "" ? {} : toClassObj(oldVal);
348
+ val = val === "" ? {} : toClassObj(val);
349
+ for (let k in oldVal) {
350
+ if (!(k in val)) {
351
+ tokenListRemove.call(this.classList, k);
352
+ }
353
+ }
354
+ for (let k in val) {
355
+ if (val[k] !== oldVal[k]) {
356
+ tokenListAdd.call(this.classList, k);
357
+ }
358
+ }
359
+ }
360
+ // ---------------------------------------------------------------------------
361
+ // Style setters
362
+ // ---------------------------------------------------------------------------
362
363
  function setStyle(val) {
363
364
  val = val === "" ? {} : toStyleObj(val);
364
365
  const style = this.style;
@@ -370,18 +371,19 @@ function updateStyle(val, oldVal) {
370
371
  oldVal = oldVal === "" ? {} : toStyleObj(oldVal);
371
372
  val = val === "" ? {} : toStyleObj(val);
372
373
  const style = this.style;
373
- // remove old styles
374
374
  for (let prop in oldVal) {
375
375
  if (!(prop in val)) {
376
376
  style.removeProperty(prop);
377
377
  }
378
378
  }
379
- // set new/changed styles
380
379
  for (let prop in val) {
381
380
  if (val[prop] !== oldVal[prop]) {
382
381
  style.setProperty(prop, val[prop]);
383
382
  }
384
383
  }
384
+ if (!style.cssText) {
385
+ removeAttribute.call(this, "style");
386
+ }
385
387
  }
386
388
 
387
389
  /**
@@ -2000,51 +2002,11 @@ function untrack(fn) {
2000
2002
  // Maps fibers to thrown errors
2001
2003
  const fibersInError = new WeakMap();
2002
2004
  const nodeErrorHandlers = new WeakMap();
2003
- function destroyApp(app, error) {
2004
- try {
2005
- app.destroy();
2006
- }
2007
- catch (e) {
2008
- // mute all errors here because we are in a corrupted state anyway
2009
- }
2010
- const e = Object.assign(new OwlError(`[Owl] Unhandled error. Destroying the root component`), {
2011
- cause: error,
2012
- });
2013
- return e;
2014
- }
2015
- function _handleError(node, error) {
2016
- if (!node) {
2017
- return false;
2018
- }
2019
- const fiber = node.fiber;
2020
- if (fiber) {
2021
- fibersInError.set(fiber, error);
2022
- }
2023
- const errorHandlers = nodeErrorHandlers.get(node);
2024
- if (errorHandlers) {
2025
- let handled = false;
2026
- // execute in the opposite order
2027
- const finalize = () => destroyApp(node.app, error);
2028
- for (let i = errorHandlers.length - 1; i >= 0; i--) {
2029
- try {
2030
- errorHandlers[i](error, finalize);
2031
- handled = true;
2032
- break;
2033
- }
2034
- catch (e) {
2035
- error = e;
2036
- }
2037
- }
2038
- if (handled) {
2039
- return true;
2040
- }
2041
- }
2042
- return _handleError(node.parent, error);
2043
- }
2044
2005
  function handleError(params) {
2045
2006
  let { error } = params;
2046
- const node = "node" in params ? params.node : params.fiber.node;
2007
+ let node = "node" in params ? params.node : params.fiber.node;
2047
2008
  const fiber = "fiber" in params ? params.fiber : node.fiber;
2009
+ const app = node.app;
2048
2010
  if (fiber) {
2049
2011
  // resets the fibers on components if possible. This is important so that
2050
2012
  // new renderings can be properly included in the initial one, if any.
@@ -2056,10 +2018,43 @@ function handleError(params) {
2056
2018
  } while (current);
2057
2019
  fibersInError.set(fiber.root, error);
2058
2020
  }
2059
- const handled = _handleError(node, error);
2060
- if (!handled) {
2061
- throw destroyApp(node.app, error);
2021
+ const finalize = () => {
2022
+ try {
2023
+ app.destroy();
2024
+ }
2025
+ catch (e) {
2026
+ // mute all errors here because we are in a corrupted state anyway
2027
+ }
2028
+ return Object.assign(new OwlError(`[Owl] Unhandled error. Destroying the root component`), {
2029
+ cause: error,
2030
+ });
2031
+ };
2032
+ // Walk up the component tree looking for error handlers
2033
+ while (node) {
2034
+ const nodeFiber = node.fiber;
2035
+ if (nodeFiber) {
2036
+ fibersInError.set(nodeFiber, error);
2037
+ }
2038
+ const errorHandlers = nodeErrorHandlers.get(node);
2039
+ if (errorHandlers) {
2040
+ // execute in the opposite order
2041
+ for (let i = errorHandlers.length - 1; i >= 0; i--) {
2042
+ try {
2043
+ errorHandlers[i](error, finalize);
2044
+ return; // handled
2045
+ }
2046
+ catch (e) {
2047
+ error = e;
2048
+ }
2049
+ }
2050
+ }
2051
+ node = node.parent;
2062
2052
  }
2053
+ // No handler found — create the OwlError, then let the app handle it.
2054
+ // app._handleError is called after error creation, so it doesn't appear
2055
+ // in the error's .stack property.
2056
+ const owlError = finalize();
2057
+ app._handleError(owlError);
2063
2058
  }
2064
2059
 
2065
2060
  function makeChildFiber(node, parent) {
@@ -2195,7 +2190,7 @@ class Fiber {
2195
2190
  this.bdom = node.renderFn();
2196
2191
  }
2197
2192
  catch (e) {
2198
- node.app.handleError({ node, error: e });
2193
+ handleError({ node, error: e });
2199
2194
  }
2200
2195
  setComputation(c);
2201
2196
  root.setCounter(root.counter - 1);
@@ -2265,7 +2260,7 @@ class RootFiber extends Fiber {
2265
2260
  fiber.node.willUnmount = [];
2266
2261
  }
2267
2262
  this.locked = false;
2268
- node.app.handleError({ fiber: current || this, error: e });
2263
+ handleError({ fiber: current || this, error: e });
2269
2264
  }
2270
2265
  }
2271
2266
  setCounter(newValue) {
@@ -2321,7 +2316,7 @@ class MountFiber extends RootFiber {
2321
2316
  }
2322
2317
  }
2323
2318
  catch (e) {
2324
- this.node.app.handleError({ fiber: current, error: e });
2319
+ handleError({ fiber: current, error: e });
2325
2320
  }
2326
2321
  }
2327
2322
  }
@@ -2399,7 +2394,7 @@ class ComponentNode {
2399
2394
  await Promise.all(promises);
2400
2395
  }
2401
2396
  catch (e) {
2402
- this.app.handleError({ node: this, error: e });
2397
+ handleError({ node: this, error: e });
2403
2398
  return;
2404
2399
  }
2405
2400
  if (this.status === 0 /* STATUS.NEW */ && this.fiber === fiber) {
@@ -2489,7 +2484,7 @@ class ComponentNode {
2489
2484
  }
2490
2485
  }
2491
2486
  catch (e) {
2492
- this.app.handleError({ error: e, node: this });
2487
+ handleError({ error: e, node: this });
2493
2488
  }
2494
2489
  }
2495
2490
  for (const computation of this.computations) {
@@ -5672,7 +5667,7 @@ function compile(template, options = {
5672
5667
  }
5673
5668
 
5674
5669
  // do not modify manually. This file is generated by the release script.
5675
- const version = "3.0.0-alpha.21";
5670
+ const version = "3.0.0-alpha.23";
5676
5671
 
5677
5672
  function effect(fn) {
5678
5673
  const computation = createComputation(() => {
@@ -5870,8 +5865,33 @@ class Scheduler {
5870
5865
  node._destroy();
5871
5866
  }
5872
5867
  this.cancelledNodes.clear();
5873
- for (let task of this.tasks) {
5874
- this.processFiber(task);
5868
+ for (let fiber of this.tasks) {
5869
+ if (fiber.root !== fiber) {
5870
+ this.tasks.delete(fiber);
5871
+ continue;
5872
+ }
5873
+ const hasError = fibersInError.has(fiber);
5874
+ if (hasError && fiber.counter !== 0) {
5875
+ this.tasks.delete(fiber);
5876
+ continue;
5877
+ }
5878
+ if (fiber.node.status === 3 /* STATUS.DESTROYED */) {
5879
+ this.tasks.delete(fiber);
5880
+ continue;
5881
+ }
5882
+ if (fiber.counter === 0) {
5883
+ if (!hasError) {
5884
+ fiber.complete();
5885
+ }
5886
+ // at this point, the fiber should have been applied to the DOM, so we can
5887
+ // remove it from the task list. If it is not the case, it means that there
5888
+ // was an error and an error handler triggered a new rendering that recycled
5889
+ // the fiber, so in that case, we actually want to keep the fiber around,
5890
+ // otherwise it will just be ignored.
5891
+ if (fiber.appliedToDom) {
5892
+ this.tasks.delete(fiber);
5893
+ }
5894
+ }
5875
5895
  }
5876
5896
  for (let task of this.tasks) {
5877
5897
  if (task.node.status === 3 /* STATUS.DESTROYED */) {
@@ -5880,34 +5900,6 @@ class Scheduler {
5880
5900
  }
5881
5901
  this.processing = false;
5882
5902
  }
5883
- processFiber(fiber) {
5884
- if (fiber.root !== fiber) {
5885
- this.tasks.delete(fiber);
5886
- return;
5887
- }
5888
- const hasError = fibersInError.has(fiber);
5889
- if (hasError && fiber.counter !== 0) {
5890
- this.tasks.delete(fiber);
5891
- return;
5892
- }
5893
- if (fiber.node.status === 3 /* STATUS.DESTROYED */) {
5894
- this.tasks.delete(fiber);
5895
- return;
5896
- }
5897
- if (fiber.counter === 0) {
5898
- if (!hasError) {
5899
- fiber.complete();
5900
- }
5901
- // at this point, the fiber should have been applied to the DOM, so we can
5902
- // remove it from the task list. If it is not the case, it means that there
5903
- // was an error and an error handler triggered a new rendering that recycled
5904
- // the fiber, so in that case, we actually want to keep the fiber around,
5905
- // otherwise it will just be ignored.
5906
- if (fiber.appliedToDom) {
5907
- this.tasks.delete(fiber);
5908
- }
5909
- }
5910
- }
5911
5903
  }
5912
5904
 
5913
5905
  let hasBeenLogged = false;
@@ -6007,8 +5999,8 @@ class App extends TemplateSet {
6007
5999
  this.scheduler.processTasks();
6008
6000
  apps.delete(this);
6009
6001
  }
6010
- handleError(...args) {
6011
- return handleError(...args);
6002
+ _handleError(error) {
6003
+ throw error;
6012
6004
  }
6013
6005
  }
6014
6006
  async function mount(C, target, config = {}) {
@@ -6066,14 +6058,20 @@ const mainEventHandler = (data, ev, currentTarget) => {
6066
6058
  // hooks
6067
6059
  // -----------------------------------------------------------------------------
6068
6060
  function decorate(node, f, hookName) {
6069
- const result = f.bind(node.component);
6070
6061
  if (node.app.dev) {
6071
- const suffix = f.name ? ` <${f.name}>` : "";
6072
- Reflect.defineProperty(result, "name", {
6073
- value: hookName + suffix,
6074
- });
6062
+ const component = node.component;
6063
+ const componentName = component ? component.constructor.name : "Component";
6064
+ const name = `${componentName}.${hookName}`;
6065
+ // Create a named wrapper so the name appears in stack traces.
6066
+ // V8 uses computed property keys as inferred function names.
6067
+ const wrapper = {
6068
+ [name]() {
6069
+ return f.call(component);
6070
+ },
6071
+ };
6072
+ return wrapper[name];
6075
6073
  }
6076
- return result;
6074
+ return f.bind(node.component);
6077
6075
  }
6078
6076
  function onWillStart(fn) {
6079
6077
  const { node } = getContext("component");
@@ -6331,22 +6329,30 @@ class Registry {
6331
6329
  }
6332
6330
  }
6333
6331
 
6334
- const anyType = function validateAny() { };
6335
- const booleanType = function validateBoolean(context) {
6336
- if (typeof context.value !== "boolean") {
6337
- context.addIssue({ message: "value is not a boolean" });
6338
- }
6339
- };
6340
- const numberType = function validateNumber(context) {
6341
- if (typeof context.value !== "number") {
6342
- context.addIssue({ message: "value is not a number" });
6343
- }
6344
- };
6345
- const stringType = function validateString(context) {
6346
- if (typeof context.value !== "string") {
6347
- context.addIssue({ message: "value is not a string" });
6348
- }
6349
- };
6332
+ function anyType() {
6333
+ return function validateAny() { };
6334
+ }
6335
+ function booleanType() {
6336
+ return function validateBoolean(context) {
6337
+ if (typeof context.value !== "boolean") {
6338
+ context.addIssue({ message: "value is not a boolean" });
6339
+ }
6340
+ };
6341
+ }
6342
+ function numberType() {
6343
+ return function validateNumber(context) {
6344
+ if (typeof context.value !== "number") {
6345
+ context.addIssue({ message: "value is not a number" });
6346
+ }
6347
+ };
6348
+ }
6349
+ function stringType() {
6350
+ return function validateString(context) {
6351
+ if (typeof context.value !== "string") {
6352
+ context.addIssue({ message: "value is not a string" });
6353
+ }
6354
+ };
6355
+ }
6350
6356
  function arrayType(elementType) {
6351
6357
  return function validateArray(context) {
6352
6358
  if (!Array.isArray(context.value)) {
@@ -6537,6 +6543,9 @@ function reactiveValueType(type) {
6537
6543
  }
6538
6544
  };
6539
6545
  }
6546
+ function componentType() {
6547
+ return constructorType(Component);
6548
+ }
6540
6549
  function ref(type) {
6541
6550
  return union([literalType(null), instanceType(type)]);
6542
6551
  }
@@ -6545,6 +6554,7 @@ const types = {
6545
6554
  any: anyType,
6546
6555
  array: arrayType,
6547
6556
  boolean: booleanType,
6557
+ component: componentType,
6548
6558
  constructor: constructorType,
6549
6559
  customValidator: customValidator,
6550
6560
  function: functionType,
@@ -6813,6 +6823,6 @@ exports.whenReady = whenReady;
6813
6823
  exports.xml = xml;
6814
6824
 
6815
6825
 
6816
- __info__.date = '2026-04-02T11:14:58.432Z';
6817
- __info__.hash = '9ca35d8';
6826
+ __info__.date = '2026-04-10T07:28:23.029Z';
6827
+ __info__.hash = 'e5e6d92';
6818
6828
  __info__.url = 'https://github.com/odoo/owl';