@odoo/owl 3.0.0-alpha.40 → 3.0.0-alpha.42

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 CHANGED
@@ -417,18 +417,15 @@ function getTargetKeyAtom(target, key) {
417
417
  function onReadTargetKey(target, key, atom) {
418
418
  onReadAtom(atom ?? getTargetKeyAtom(target, key));
419
419
  }
420
- function onWriteTargetKey(target, key, atom) {
421
- if (!atom) {
422
- const keyToAtomItem = targetToKeysToAtomItem.get(target);
423
- if (!keyToAtomItem) {
424
- return;
425
- }
426
- if (!keyToAtomItem.has(key)) {
427
- return;
428
- }
429
- atom = keyToAtomItem.get(key);
420
+ function onWriteTargetKey(target, key) {
421
+ const keyToAtomItem = targetToKeysToAtomItem.get(target);
422
+ if (!keyToAtomItem) {
423
+ return;
424
+ }
425
+ if (!keyToAtomItem.has(key)) {
426
+ return;
430
427
  }
431
- onWriteAtom(atom);
428
+ onWriteAtom(keyToAtomItem.get(key));
432
429
  }
433
430
  var targets = /* @__PURE__ */ new WeakMap();
434
431
  var proxyCache = /* @__PURE__ */ new WeakMap();
@@ -485,18 +482,30 @@ function basicProxyHandler(atom) {
485
482
  const hadKey = objectHasOwnProperty.call(target, key);
486
483
  const originalValue = Reflect.get(target, key, receiver);
487
484
  const ret = Reflect.set(target, key, toRaw(value), receiver);
488
- if (!hadKey && objectHasOwnProperty.call(target, key)) {
489
- onWriteTargetKey(target, KEYCHANGES, atom);
490
- }
491
- if (originalValue !== Reflect.get(target, key, receiver) || key === "length" && Array.isArray(target)) {
492
- onWriteTargetKey(target, key, atom);
485
+ const keyCreated = !hadKey && objectHasOwnProperty.call(target, key);
486
+ const valueChanged = originalValue !== Reflect.get(target, key, receiver);
487
+ if (atom) {
488
+ if (keyCreated || valueChanged) {
489
+ onWriteAtom(atom);
490
+ }
491
+ } else {
492
+ if (keyCreated) {
493
+ onWriteTargetKey(target, KEYCHANGES);
494
+ }
495
+ if (valueChanged || key === "length" && Array.isArray(target)) {
496
+ onWriteTargetKey(target, key);
497
+ }
493
498
  }
494
499
  return ret;
495
500
  },
496
501
  deleteProperty(target, key) {
497
502
  const ret = Reflect.deleteProperty(target, key);
498
- onWriteTargetKey(target, KEYCHANGES, atom);
499
- onWriteTargetKey(target, key, atom);
503
+ if (atom) {
504
+ onWriteAtom(atom);
505
+ } else {
506
+ onWriteTargetKey(target, KEYCHANGES);
507
+ onWriteTargetKey(target, key);
508
+ }
500
509
  return ret;
501
510
  },
502
511
  ownKeys(target) {
@@ -512,26 +521,26 @@ function basicProxyHandler(atom) {
512
521
  function makeKeyObserver(methodName, target, atom) {
513
522
  return (key) => {
514
523
  key = toRaw(key);
515
- onReadTargetKey(target, key, atom);
524
+ onReadTargetKey(target, key, null);
516
525
  return possiblyReactive(target[methodName](key), atom);
517
526
  };
518
527
  }
519
528
  function makeIteratorObserver(methodName, target, atom) {
520
529
  return function* () {
521
- onReadTargetKey(target, KEYCHANGES, atom);
530
+ onReadTargetKey(target, KEYCHANGES, null);
522
531
  const keys = target.keys();
523
532
  for (const item of target[methodName]()) {
524
533
  const key = keys.next().value;
525
- onReadTargetKey(target, key, atom);
534
+ onReadTargetKey(target, key, null);
526
535
  yield possiblyReactive(item, atom);
527
536
  }
528
537
  };
529
538
  }
530
539
  function makeForEachObserver(target, atom) {
531
540
  return function forEach(forEachCb, thisArg) {
532
- onReadTargetKey(target, KEYCHANGES, atom);
541
+ onReadTargetKey(target, KEYCHANGES, null);
533
542
  target.forEach(function(val, key, targetObj) {
534
- onReadTargetKey(target, key, atom);
543
+ onReadTargetKey(target, key, null);
535
544
  forEachCb.call(
536
545
  thisArg,
537
546
  possiblyReactive(val, atom),
@@ -541,7 +550,7 @@ function makeForEachObserver(target, atom) {
541
550
  }, thisArg);
542
551
  };
543
552
  }
544
- function delegateAndNotify(setterName, getterName, target, atom) {
553
+ function delegateAndNotify(setterName, getterName, target) {
545
554
  return (key, value) => {
546
555
  key = toRaw(key);
547
556
  const hadKey = target.has(key);
@@ -549,61 +558,61 @@ function delegateAndNotify(setterName, getterName, target, atom) {
549
558
  const ret = target[setterName](key, value);
550
559
  const hasKey = target.has(key);
551
560
  if (hadKey !== hasKey) {
552
- onWriteTargetKey(target, KEYCHANGES, atom);
561
+ onWriteTargetKey(target, KEYCHANGES);
553
562
  }
554
563
  if (originalValue !== target[getterName](key)) {
555
- onWriteTargetKey(target, key, atom);
564
+ onWriteTargetKey(target, key);
556
565
  }
557
566
  return ret;
558
567
  };
559
568
  }
560
- function makeClearNotifier(target, atom) {
569
+ function makeClearNotifier(target) {
561
570
  return () => {
562
571
  const allKeys = [...target.keys()];
563
572
  target.clear();
564
- onWriteTargetKey(target, KEYCHANGES, atom);
573
+ onWriteTargetKey(target, KEYCHANGES);
565
574
  for (const key of allKeys) {
566
- onWriteTargetKey(target, key, atom);
575
+ onWriteTargetKey(target, key);
567
576
  }
568
577
  };
569
578
  }
570
579
  var rawTypeToFuncHandlers = {
571
580
  Set: (target, atom) => ({
572
581
  has: makeKeyObserver("has", target, atom),
573
- add: delegateAndNotify("add", "has", target, atom),
574
- delete: delegateAndNotify("delete", "has", target, atom),
582
+ add: delegateAndNotify("add", "has", target),
583
+ delete: delegateAndNotify("delete", "has", target),
575
584
  keys: makeIteratorObserver("keys", target, atom),
576
585
  values: makeIteratorObserver("values", target, atom),
577
586
  entries: makeIteratorObserver("entries", target, atom),
578
587
  [Symbol.iterator]: makeIteratorObserver(Symbol.iterator, target, atom),
579
588
  forEach: makeForEachObserver(target, atom),
580
- clear: makeClearNotifier(target, atom),
589
+ clear: makeClearNotifier(target),
581
590
  get size() {
582
- onReadTargetKey(target, KEYCHANGES, atom);
591
+ onReadTargetKey(target, KEYCHANGES, null);
583
592
  return target.size;
584
593
  }
585
594
  }),
586
595
  Map: (target, atom) => ({
587
596
  has: makeKeyObserver("has", target, atom),
588
597
  get: makeKeyObserver("get", target, atom),
589
- set: delegateAndNotify("set", "get", target, atom),
590
- delete: delegateAndNotify("delete", "has", target, atom),
598
+ set: delegateAndNotify("set", "get", target),
599
+ delete: delegateAndNotify("delete", "has", target),
591
600
  keys: makeIteratorObserver("keys", target, atom),
592
601
  values: makeIteratorObserver("values", target, atom),
593
602
  entries: makeIteratorObserver("entries", target, atom),
594
603
  [Symbol.iterator]: makeIteratorObserver(Symbol.iterator, target, atom),
595
604
  forEach: makeForEachObserver(target, atom),
596
- clear: makeClearNotifier(target, atom),
605
+ clear: makeClearNotifier(target),
597
606
  get size() {
598
- onReadTargetKey(target, KEYCHANGES, atom);
607
+ onReadTargetKey(target, KEYCHANGES, null);
599
608
  return target.size;
600
609
  }
601
610
  }),
602
611
  WeakMap: (target, atom) => ({
603
612
  has: makeKeyObserver("has", target, atom),
604
613
  get: makeKeyObserver("get", target, atom),
605
- set: delegateAndNotify("set", "get", target, atom),
606
- delete: delegateAndNotify("delete", "has", target, atom)
614
+ set: delegateAndNotify("set", "get", target),
615
+ delete: delegateAndNotify("delete", "has", target)
607
616
  })
608
617
  };
609
618
  function collectionsProxyHandler(target, targetRawType, atom) {
@@ -650,16 +659,16 @@ function triggerSignal(signal2) {
650
659
  function signalRef() {
651
660
  return buildSignal(null, (atom) => atom.value);
652
661
  }
653
- function signalArray(initialValue) {
662
+ function signalArray(initialValue = []) {
654
663
  return buildSignal(initialValue, (atom) => proxifyTarget(atom.value, atom));
655
664
  }
656
- function signalObject(initialValue) {
665
+ function signalObject(initialValue = {}) {
657
666
  return buildSignal(initialValue, (atom) => proxifyTarget(atom.value, atom));
658
667
  }
659
- function signalMap(initialValue) {
668
+ function signalMap(initialValue = /* @__PURE__ */ new Map()) {
660
669
  return buildSignal(initialValue, (atom) => proxifyTarget(atom.value, atom));
661
670
  }
662
- function signalSet(initialValue) {
671
+ function signalSet(initialValue = /* @__PURE__ */ new Set()) {
663
672
  return buildSignal(initialValue, (atom) => proxifyTarget(atom.value, atom));
664
673
  }
665
674
  function signal(value) {
@@ -1054,6 +1063,16 @@ function intersection(types22) {
1054
1063
  }
1055
1064
  });
1056
1065
  validate[intersectionSymbol] = types22;
1066
+ validate.toShape = () => {
1067
+ const shape = {};
1068
+ for (const member of types22) {
1069
+ const memberShape = typeof member.toShape === "function" ? member.toShape() : void 0;
1070
+ if (memberShape && !Array.isArray(memberShape)) {
1071
+ Object.assign(shape, memberShape);
1072
+ }
1073
+ }
1074
+ return shape;
1075
+ };
1057
1076
  return validate;
1058
1077
  }
1059
1078
  function literalType(literal) {
@@ -1129,6 +1148,7 @@ function objectType(schema = {}) {
1129
1148
  if (!Array.isArray(schema)) {
1130
1149
  validate[shapeSymbol] = schema;
1131
1150
  }
1151
+ validate.toShape = () => schema;
1132
1152
  return validate;
1133
1153
  }
1134
1154
  function strictObjectType(schema) {
@@ -1138,6 +1158,7 @@ function strictObjectType(schema) {
1138
1158
  if (!Array.isArray(schema)) {
1139
1159
  validate[shapeSymbol] = schema;
1140
1160
  }
1161
+ validate.toShape = () => schema;
1141
1162
  return validate;
1142
1163
  }
1143
1164
  function promiseType(type) {
@@ -1565,7 +1586,7 @@ function markup(valueOrStrings, ...placeholders) {
1565
1586
  }
1566
1587
 
1567
1588
  // ../owl-runtime/dist/owl-runtime.es.js
1568
- var version = "3.0.0-alpha.40";
1589
+ var version = "3.0.0-alpha.42";
1569
1590
  var fibersInError = /* @__PURE__ */ new WeakMap();
1570
1591
  var nodeErrorHandlers = /* @__PURE__ */ new WeakMap();
1571
1592
  function invokeErrorHandlers(node, error, finalize, markFibers) {
@@ -1958,9 +1979,11 @@ function updateStyle(val, oldVal) {
1958
1979
  style.removeProperty(prop);
1959
1980
  }
1960
1981
  }
1982
+ let changed = false;
1961
1983
  for (let prop in val) {
1962
- if (val[prop] !== oldVal[prop]) {
1984
+ if (changed || val[prop] !== oldVal[prop]) {
1963
1985
  setStyleProp(style, prop, val[prop]);
1986
+ changed = true;
1964
1987
  }
1965
1988
  }
1966
1989
  if (!style.cssText) {
@@ -3187,6 +3210,7 @@ function status(entity) {
3187
3210
  return "destroyed";
3188
3211
  }
3189
3212
  }
3213
+ var MAX_RENDER_ITERATIONS = 1e3;
3190
3214
  function makeChildFiber(node, parent) {
3191
3215
  let current = node.fiber;
3192
3216
  if (current) {
@@ -3199,6 +3223,7 @@ function makeRootFiber(node) {
3199
3223
  let current = node.fiber;
3200
3224
  if (current) {
3201
3225
  let root = current.root;
3226
+ root.renderCount++;
3202
3227
  root.locked = true;
3203
3228
  root.setCounter(root.counter + 1 - cancelFibers(current.children));
3204
3229
  root.locked = false;
@@ -3293,6 +3318,15 @@ var Fiber = class {
3293
3318
  const node = this.node;
3294
3319
  const root = this.root;
3295
3320
  if (root) {
3321
+ if (root.renderCount > MAX_RENDER_ITERATIONS) {
3322
+ handleError({
3323
+ node,
3324
+ error: new OwlError(
3325
+ `Maximum render iterations (${MAX_RENDER_ITERATIONS}) exceeded. Component "${node.componentName}" is stuck in a render loop: rendering it keeps triggering another render before the DOM is updated. A common cause is updating reactive state during render or setup() \u2014 e.g. calling a parent's state setter from a child's setup().`
3326
+ )
3327
+ });
3328
+ return;
3329
+ }
3296
3330
  const c = getCurrentComputation();
3297
3331
  removeSources(node.signalComputation);
3298
3332
  setComputation(node.signalComputation);
@@ -3315,6 +3349,9 @@ var Fiber = class {
3315
3349
  };
3316
3350
  var RootFiber = class extends Fiber {
3317
3351
  counter = 1;
3352
+ // Number of times this (uncommitted) fiber has been recycled by makeRootFiber.
3353
+ // Climbs without bound only in a render loop; see issue #1968.
3354
+ renderCount = 0;
3318
3355
  // only add stuff in this if they have registered some hooks
3319
3356
  willPatch = [];
3320
3357
  patched = [];
@@ -4296,6 +4333,13 @@ var App = class _App extends TemplateSet {
4296
4333
  let error = null;
4297
4334
  try {
4298
4335
  node = new ComponentNode(Root, props2, this, null, null);
4336
+ const subConfig = config3;
4337
+ if (subConfig.pluginManager) {
4338
+ node.pluginManager = subConfig.pluginManager;
4339
+ }
4340
+ if (subConfig.onError) {
4341
+ nodeErrorHandlers.set(node, [subConfig.onError]);
4342
+ }
4299
4343
  } catch (e) {
4300
4344
  error = e;
4301
4345
  reject(e);
@@ -4356,7 +4400,9 @@ var App = class _App extends TemplateSet {
4356
4400
  return promise;
4357
4401
  };
4358
4402
  const root = {
4359
- node,
4403
+ get prepared() {
4404
+ return fiber ? fiber.counter === 0 : false;
4405
+ },
4360
4406
  promise,
4361
4407
  prepare,
4362
4408
  mount: mount3,
@@ -4386,6 +4432,9 @@ var App = class _App extends TemplateSet {
4386
4432
  };
4387
4433
  async function mount2(C, target, config3 = {}) {
4388
4434
  const app = new App(config3);
4435
+ if (app.pluginManager.status < STATUS.MOUNTED) {
4436
+ await app.pluginManager.ready;
4437
+ }
4389
4438
  const root = app.createRoot(C, config3);
4390
4439
  return root.mount(target, config3);
4391
4440
  }
@@ -4622,9 +4671,18 @@ var Portal = class extends Component {
4622
4671
  if (!target) {
4623
4672
  return;
4624
4673
  }
4625
- root = app.createRoot(PortalContent, { props: { slots } });
4626
- root.node.pluginManager = portalNode.pluginManager;
4627
- nodeErrorHandlers.set(root.node, [forwardErrorToParent(portalNode)]);
4674
+ root = app.createRoot(PortalContent, {
4675
+ props: { slots },
4676
+ // Forward the plugin chain from this Portal (createRoot defaults
4677
+ // sub-roots to the app-level plugin manager) so `providePlugins`
4678
+ // contributions from ancestors are visible inside the portaled content.
4679
+ pluginManager: portalNode.pluginManager,
4680
+ // Route errors from the portaled subtree back through Portal's parent
4681
+ // chain so consumer `onError` handlers still catch them. Without this,
4682
+ // sub-root errors would propagate to app._handleError and tear down
4683
+ // the whole app.
4684
+ onError: forwardErrorToParent(portalNode)
4685
+ });
4628
4686
  root.mount(target);
4629
4687
  return tearDown;
4630
4688
  });
@@ -4659,13 +4717,18 @@ var Suspense = class extends Component {
4659
4717
  setup() {
4660
4718
  const suspenseNode = this.__owl__;
4661
4719
  const root = suspenseNode.app.createRoot(SuspenseHost, {
4662
- props: { slots: this.props.slots }
4720
+ props: { slots: this.props.slots },
4721
+ // Thread the plugin manager so `providePlugins` contributions from
4722
+ // ancestors are visible inside the default slot. (createRoot defaults
4723
+ // sub-roots to the app-level plugin manager; override here.) Destroy
4724
+ // cascade is handled explicitly below via `onWillDestroy`.
4725
+ pluginManager: suspenseNode.pluginManager,
4726
+ // Route errors from the sub-root back into Suspense's parent chain so
4727
+ // consumer `onError` handlers still catch descendant failures.
4728
+ onError: forwardErrorToParent(suspenseNode)
4663
4729
  });
4664
- root.node.pluginManager = suspenseNode.pluginManager;
4665
- nodeErrorHandlers.set(root.node, [forwardErrorToParent(suspenseNode)]);
4666
4730
  root.prepare().then(() => this.prepared.set(true));
4667
- const fiber = root.node.fiber;
4668
- if (fiber && fiber.counter === 0) {
4731
+ if (root.prepared) {
4669
4732
  this.prepared.set(true);
4670
4733
  }
4671
4734
  onMounted(() => this.mounted.set(true));
@@ -4708,8 +4771,8 @@ var blockDom = {
4708
4771
  };
4709
4772
  var __info__ = {
4710
4773
  version: App.version,
4711
- date: "2026-06-26T12:29:22.680Z",
4712
- hash: "5565ac15",
4774
+ date: "2026-07-07T08:36:25.562Z",
4775
+ hash: "1d192035",
4713
4776
  url: "https://github.com/odoo/owl"
4714
4777
  };
4715
4778