@odoo/owl 2.0.0 → 2.0.2

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
@@ -42,8 +42,11 @@ class VToggler {
42
42
  this.parentEl = parent;
43
43
  this.child.mount(parent, afterNode);
44
44
  }
45
- moveBefore(other, afterNode) {
46
- this.child.moveBefore(other ? other.child : null, afterNode);
45
+ moveBeforeDOMNode(node, parent) {
46
+ this.child.moveBeforeDOMNode(node, parent);
47
+ }
48
+ moveBeforeVNode(other, afterNode) {
49
+ this.moveBeforeDOMNode((other && other.firstNode()) || afterNode);
47
50
  }
48
51
  patch(other, withBeforeRemove) {
49
52
  if (this === other) {
@@ -419,7 +422,22 @@ class VMulti {
419
422
  this.anchors = anchors;
420
423
  this.parentEl = parent;
421
424
  }
422
- moveBefore(other, afterNode) {
425
+ moveBeforeDOMNode(node, parent = this.parentEl) {
426
+ this.parentEl = parent;
427
+ const children = this.children;
428
+ const anchors = this.anchors;
429
+ for (let i = 0, l = children.length; i < l; i++) {
430
+ let child = children[i];
431
+ if (child) {
432
+ child.moveBeforeDOMNode(node, parent);
433
+ }
434
+ else {
435
+ const anchor = anchors[i];
436
+ nodeInsertBefore$3.call(parent, anchor, node);
437
+ }
438
+ }
439
+ }
440
+ moveBeforeVNode(other, afterNode) {
423
441
  if (other) {
424
442
  const next = other.children[0];
425
443
  afterNode = (next ? next.firstNode() : other.anchors[0]) || null;
@@ -430,7 +448,7 @@ class VMulti {
430
448
  for (let i = 0, l = children.length; i < l; i++) {
431
449
  let child = children[i];
432
450
  if (child) {
433
- child.moveBefore(null, afterNode);
451
+ child.moveBeforeVNode(null, afterNode);
434
452
  }
435
453
  else {
436
454
  const anchor = anchors[i];
@@ -528,9 +546,12 @@ class VSimpleNode {
528
546
  nodeInsertBefore$2.call(parent, node, afterNode);
529
547
  this.el = node;
530
548
  }
531
- moveBefore(other, afterNode) {
532
- const target = other ? other.el : afterNode;
533
- nodeInsertBefore$2.call(this.parentEl, this.el, target);
549
+ moveBeforeDOMNode(node, parent = this.parentEl) {
550
+ this.parentEl = parent;
551
+ nodeInsertBefore$2.call(parent, this.el, node);
552
+ }
553
+ moveBeforeVNode(other, afterNode) {
554
+ nodeInsertBefore$2.call(this.parentEl, this.el, other ? other.el : afterNode);
534
555
  }
535
556
  beforeRemove() { }
536
557
  remove() {
@@ -972,9 +993,12 @@ function createBlockClass(template, ctx) {
972
993
  firstNode() {
973
994
  return this.el;
974
995
  }
975
- moveBefore(other, afterNode) {
976
- const target = other ? other.el : afterNode;
977
- nodeInsertBefore.call(this.parentEl, this.el, target);
996
+ moveBeforeDOMNode(node, parent = this.parentEl) {
997
+ this.parentEl = parent;
998
+ nodeInsertBefore.call(parent, this.el, node);
999
+ }
1000
+ moveBeforeVNode(other, afterNode) {
1001
+ nodeInsertBefore.call(this.parentEl, this.el, other ? other.el : afterNode);
978
1002
  }
979
1003
  toString() {
980
1004
  const div = document.createElement("div");
@@ -1111,14 +1135,22 @@ class VList {
1111
1135
  }
1112
1136
  this.parentEl = parent;
1113
1137
  }
1114
- moveBefore(other, afterNode) {
1138
+ moveBeforeDOMNode(node, parent = this.parentEl) {
1139
+ this.parentEl = parent;
1140
+ const children = this.children;
1141
+ for (let i = 0, l = children.length; i < l; i++) {
1142
+ children[i].moveBeforeDOMNode(node, parent);
1143
+ }
1144
+ parent.insertBefore(this.anchor, node);
1145
+ }
1146
+ moveBeforeVNode(other, afterNode) {
1115
1147
  if (other) {
1116
1148
  const next = other.children[0];
1117
1149
  afterNode = (next ? next.firstNode() : other.anchor) || null;
1118
1150
  }
1119
1151
  const children = this.children;
1120
1152
  for (let i = 0, l = children.length; i < l; i++) {
1121
- children[i].moveBefore(null, afterNode);
1153
+ children[i].moveBeforeVNode(null, afterNode);
1122
1154
  }
1123
1155
  this.parentEl.insertBefore(this.anchor, afterNode);
1124
1156
  }
@@ -1133,7 +1165,7 @@ class VList {
1133
1165
  }
1134
1166
  this.children = ch2;
1135
1167
  const proto = ch2[0] || ch1[0];
1136
- const { mount: cMount, patch: cPatch, remove: cRemove, beforeRemove, moveBefore: cMoveBefore, firstNode: cFirstNode, } = proto;
1168
+ const { mount: cMount, patch: cPatch, remove: cRemove, beforeRemove, moveBeforeVNode: cMoveBefore, firstNode: cFirstNode, } = proto;
1137
1169
  const _anchor = this.anchor;
1138
1170
  const isOnlyChild = this.isOnlyChild;
1139
1171
  const parent = this.parentEl;
@@ -1315,13 +1347,16 @@ class VHtml {
1315
1347
  nodeInsertBefore.call(parent, textNode, afterNode);
1316
1348
  }
1317
1349
  }
1318
- moveBefore(other, afterNode) {
1319
- const target = other ? other.content[0] : afterNode;
1320
- const parent = this.parentEl;
1350
+ moveBeforeDOMNode(node, parent = this.parentEl) {
1351
+ this.parentEl = parent;
1321
1352
  for (let elem of this.content) {
1322
- nodeInsertBefore.call(parent, elem, target);
1353
+ nodeInsertBefore.call(parent, elem, node);
1323
1354
  }
1324
1355
  }
1356
+ moveBeforeVNode(other, afterNode) {
1357
+ const target = other ? other.content[0] : afterNode;
1358
+ this.moveBeforeDOMNode(target);
1359
+ }
1325
1360
  patch(other) {
1326
1361
  if (this === other) {
1327
1362
  return;
@@ -1399,7 +1434,7 @@ function createCatcher(eventsSpec) {
1399
1434
  const target = ev.target;
1400
1435
  let currentNode = self.child.firstNode();
1401
1436
  const afterNode = self.afterNode;
1402
- while (currentNode !== afterNode) {
1437
+ while (currentNode && currentNode !== afterNode) {
1403
1438
  if (currentNode.contains(target)) {
1404
1439
  return origFn.call(this, ev);
1405
1440
  }
@@ -1408,8 +1443,17 @@ function createCatcher(eventsSpec) {
1408
1443
  };
1409
1444
  }
1410
1445
  }
1411
- moveBefore(other, afterNode) {
1412
- this.child.moveBefore(other ? other.child : null, afterNode);
1446
+ moveBeforeDOMNode(node, parent = this.parentEl) {
1447
+ this.parentEl = parent;
1448
+ this.child.moveBeforeDOMNode(node, parent);
1449
+ parent.insertBefore(this.afterNode, node);
1450
+ }
1451
+ moveBeforeVNode(other, afterNode) {
1452
+ if (other) {
1453
+ // check this with @ged-odoo for use in foreach
1454
+ afterNode = other.firstNode() || afterNode;
1455
+ }
1456
+ this.child.moveBeforeVNode(other ? other.child : null, afterNode);
1413
1457
  this.parentEl.insertBefore(this.afterNode, afterNode);
1414
1458
  }
1415
1459
  patch(other, withBeforeRemove) {
@@ -1700,10 +1744,6 @@ class MountFiber extends RootFiber {
1700
1744
  }
1701
1745
  }
1702
1746
 
1703
- // Allows to get the target of a Reactive (used for making a new Reactive from the underlying object)
1704
- const TARGET = Symbol("Target");
1705
- // Escape hatch to prevent reactivity system to turn something into a reactive
1706
- const SKIP = Symbol("Skip");
1707
1747
  // Special key to subscribe to, to be notified of key creation/deletion
1708
1748
  const KEYCHANGES = Symbol("Key changes");
1709
1749
  const objectToString = Object.prototype.toString;
@@ -1744,6 +1784,7 @@ function canBeMadeReactive(value) {
1744
1784
  function possiblyReactive(val, cb) {
1745
1785
  return canBeMadeReactive(val) ? reactive(val, cb) : val;
1746
1786
  }
1787
+ const skipped = new WeakSet();
1747
1788
  /**
1748
1789
  * Mark an object or array so that it is ignored by the reactivity system
1749
1790
  *
@@ -1751,7 +1792,7 @@ function possiblyReactive(val, cb) {
1751
1792
  * @returns the object itself
1752
1793
  */
1753
1794
  function markRaw(value) {
1754
- value[SKIP] = true;
1795
+ skipped.add(value);
1755
1796
  return value;
1756
1797
  }
1757
1798
  /**
@@ -1761,7 +1802,7 @@ function markRaw(value) {
1761
1802
  * @returns the underlying value
1762
1803
  */
1763
1804
  function toRaw(value) {
1764
- return value[TARGET] || value;
1805
+ return targets.has(value) ? targets.get(value) : value;
1765
1806
  }
1766
1807
  const targetToKeysToCallbacks = new WeakMap();
1767
1808
  /**
@@ -1843,6 +1884,8 @@ function getSubscriptions(callback) {
1843
1884
  };
1844
1885
  });
1845
1886
  }
1887
+ // Maps reactive objects to the underlying target
1888
+ const targets = new WeakMap();
1846
1889
  const reactiveCache = new WeakMap();
1847
1890
  /**
1848
1891
  * Creates a reactive proxy for an object. Reading data on the reactive object
@@ -1858,7 +1901,7 @@ const reactiveCache = new WeakMap();
1858
1901
  * Subscriptions:
1859
1902
  * + Reading a property on an object will subscribe you to changes in the value
1860
1903
  * of that property.
1861
- * + Accessing an object keys (eg with Object.keys or with `for..in`) will
1904
+ * + Accessing an object's keys (eg with Object.keys or with `for..in`) will
1862
1905
  * subscribe you to the creation/deletion of keys. Checking the presence of a
1863
1906
  * key on the object with 'in' has the same effect.
1864
1907
  * - getOwnPropertyDescriptor does not currently subscribe you to the property.
@@ -1875,12 +1918,12 @@ function reactive(target, callback = () => { }) {
1875
1918
  if (!canBeMadeReactive(target)) {
1876
1919
  throw new OwlError(`Cannot make the given value reactive`);
1877
1920
  }
1878
- if (SKIP in target) {
1921
+ if (skipped.has(target)) {
1879
1922
  return target;
1880
1923
  }
1881
- const originalTarget = target[TARGET];
1882
- if (originalTarget) {
1883
- return reactive(originalTarget, callback);
1924
+ if (targets.has(target)) {
1925
+ // target is reactive, create a reactive on the underlying object instead
1926
+ return reactive(targets.get(target), callback);
1884
1927
  }
1885
1928
  if (!reactiveCache.has(target)) {
1886
1929
  reactiveCache.set(target, new WeakMap());
@@ -1893,6 +1936,7 @@ function reactive(target, callback = () => { }) {
1893
1936
  : basicProxyHandler(callback);
1894
1937
  const proxy = new Proxy(target, handler);
1895
1938
  reactivesForTarget.set(callback, proxy);
1939
+ targets.set(proxy, target);
1896
1940
  }
1897
1941
  return reactivesForTarget.get(callback);
1898
1942
  }
@@ -1904,29 +1948,27 @@ function reactive(target, callback = () => { }) {
1904
1948
  */
1905
1949
  function basicProxyHandler(callback) {
1906
1950
  return {
1907
- get(target, key, proxy) {
1908
- if (key === TARGET) {
1909
- return target;
1910
- }
1951
+ get(target, key, receiver) {
1911
1952
  // non-writable non-configurable properties cannot be made reactive
1912
1953
  const desc = Object.getOwnPropertyDescriptor(target, key);
1913
1954
  if (desc && !desc.writable && !desc.configurable) {
1914
- return Reflect.get(target, key, proxy);
1955
+ return Reflect.get(target, key, receiver);
1915
1956
  }
1916
1957
  observeTargetKey(target, key, callback);
1917
- return possiblyReactive(Reflect.get(target, key, proxy), callback);
1958
+ return possiblyReactive(Reflect.get(target, key, receiver), callback);
1918
1959
  },
1919
- set(target, key, value, proxy) {
1920
- const isNewKey = !objectHasOwnProperty.call(target, key);
1921
- const originalValue = Reflect.get(target, key, proxy);
1922
- const ret = Reflect.set(target, key, value, proxy);
1923
- if (isNewKey) {
1960
+ set(target, key, value, receiver) {
1961
+ const hadKey = objectHasOwnProperty.call(target, key);
1962
+ const originalValue = Reflect.get(target, key, receiver);
1963
+ const ret = Reflect.set(target, key, value, receiver);
1964
+ if (!hadKey && objectHasOwnProperty.call(target, key)) {
1924
1965
  notifyReactives(target, KEYCHANGES);
1925
1966
  }
1926
1967
  // While Array length may trigger the set trap, it's not actually set by this
1927
1968
  // method but is updated behind the scenes, and the trap is not called with the
1928
1969
  // new value. We disable the "same-value-optimization" for it because of that.
1929
- if (originalValue !== value || (Array.isArray(target) && key === "length")) {
1970
+ if (originalValue !== Reflect.get(target, key, receiver) ||
1971
+ (key === "length" && Array.isArray(target))) {
1930
1972
  notifyReactives(target, key);
1931
1973
  }
1932
1974
  return ret;
@@ -2102,10 +2144,8 @@ function collectionsProxyHandler(target, callback, targetRawType) {
2102
2144
  // property is read.
2103
2145
  const specialHandlers = rawTypeToFuncHandlers[targetRawType](target, callback);
2104
2146
  return Object.assign(basicProxyHandler(callback), {
2147
+ // FIXME: probably broken when part of prototype chain since we ignore the receiver
2105
2148
  get(target, key) {
2106
- if (key === TARGET) {
2107
- return target;
2108
- }
2109
2149
  if (objectHasOwnProperty.call(specialHandlers, key)) {
2110
2150
  return specialHandlers[key];
2111
2151
  }
@@ -2265,7 +2305,7 @@ class ComponentNode {
2265
2305
  this.childEnv = env;
2266
2306
  for (const key in props) {
2267
2307
  const prop = props[key];
2268
- if (prop && typeof prop === "object" && prop[TARGET]) {
2308
+ if (prop && typeof prop === "object" && targets.has(prop)) {
2269
2309
  props[key] = useState(prop);
2270
2310
  }
2271
2311
  }
@@ -2383,7 +2423,7 @@ class ComponentNode {
2383
2423
  currentNode = this;
2384
2424
  for (const key in props) {
2385
2425
  const prop = props[key];
2386
- if (prop && typeof prop === "object" && prop[TARGET]) {
2426
+ if (prop && typeof prop === "object" && targets.has(prop)) {
2387
2427
  props[key] = useState(prop);
2388
2428
  }
2389
2429
  }
@@ -2445,8 +2485,11 @@ class ComponentNode {
2445
2485
  this.children = this.fiber.childrenMap;
2446
2486
  this.fiber = null;
2447
2487
  }
2448
- moveBefore(other, afterNode) {
2449
- this.bdom.moveBefore(other ? other.bdom : null, afterNode);
2488
+ moveBeforeDOMNode(node, parent) {
2489
+ this.bdom.moveBeforeDOMNode(node, parent);
2490
+ }
2491
+ moveBeforeVNode(other, afterNode) {
2492
+ this.bdom.moveBeforeVNode(other ? other.bdom : null, afterNode);
2450
2493
  }
2451
2494
  patch() {
2452
2495
  if (this.fiber && this.fiber.parent) {
@@ -2663,7 +2706,7 @@ class Portal extends Component {
2663
2706
  if (!portal.target) {
2664
2707
  const target = document.querySelector(this.props.target);
2665
2708
  if (target) {
2666
- portal.content.moveBefore(target, null);
2709
+ portal.content.moveBeforeDOMNode(target.firstChild, target);
2667
2710
  }
2668
2711
  else {
2669
2712
  throw new OwlError("invalid portal target");
@@ -2838,7 +2881,7 @@ function callSlot(ctx, parent, key, name, dynamic, extra, defaultContent) {
2838
2881
  if (__scope) {
2839
2882
  slotScope[__scope] = extra;
2840
2883
  }
2841
- const slotBDom = __render ? __render.call(__ctx.__owl__.component, slotScope, parent, key) : null;
2884
+ const slotBDom = __render ? __render(slotScope, parent, key) : null;
2842
2885
  if (defaultContent) {
2843
2886
  let child1 = undefined;
2844
2887
  let child2 = undefined;
@@ -2846,14 +2889,13 @@ function callSlot(ctx, parent, key, name, dynamic, extra, defaultContent) {
2846
2889
  child1 = dynamic ? toggler(name, slotBDom) : slotBDom;
2847
2890
  }
2848
2891
  else {
2849
- child2 = defaultContent.call(ctx.__owl__.component, ctx, parent, key);
2892
+ child2 = defaultContent(ctx, parent, key);
2850
2893
  }
2851
2894
  return multi([child1, child2]);
2852
2895
  }
2853
2896
  return slotBDom || text("");
2854
2897
  }
2855
- function capture(ctx) {
2856
- const component = ctx.__owl__.component;
2898
+ function capture(ctx, component) {
2857
2899
  const result = ObjectCreate(component);
2858
2900
  for (let k in ctx) {
2859
2901
  result[k] = ctx[k];
@@ -2909,7 +2951,7 @@ function shallowEqual(l1, l2) {
2909
2951
  class LazyValue {
2910
2952
  constructor(fn, ctx, component, node, key) {
2911
2953
  this.fn = fn;
2912
- this.ctx = capture(ctx);
2954
+ this.ctx = capture(ctx, component);
2913
2955
  this.component = component;
2914
2956
  this.node = node;
2915
2957
  this.key = key;
@@ -2963,8 +3005,7 @@ function safeOutput(value, defaultValue) {
2963
3005
  let boundFunctions = new WeakMap();
2964
3006
  const WeakMapGet = WeakMap.prototype.get;
2965
3007
  const WeakMapSet = WeakMap.prototype.set;
2966
- function bind(ctx, fn) {
2967
- let component = ctx.__owl__.component;
3008
+ function bind(component, fn) {
2968
3009
  let boundFnMap = WeakMapGet.call(boundFunctions, component);
2969
3010
  if (!boundFnMap) {
2970
3011
  boundFnMap = new WeakMap();
@@ -3578,7 +3619,7 @@ class CodeTarget {
3578
3619
  let result = [];
3579
3620
  result.push(`function ${this.name}(ctx, node, key = "") {`);
3580
3621
  if (this.hasRef) {
3581
- result.push(` const refs = ctx.__owl__.refs;`);
3622
+ result.push(` const refs = this.__owl__.refs;`);
3582
3623
  for (let name in this.refInfo) {
3583
3624
  const [id, expr] = this.refInfo[name];
3584
3625
  result.push(` const ${id} = ${expr};`);
@@ -3963,39 +4004,6 @@ class CodeGenerator {
3963
4004
  attrs[`block-attribute-${selectedId}`] = "selected";
3964
4005
  }
3965
4006
  }
3966
- // event handlers
3967
- for (let ev in ast.on) {
3968
- const name = this.generateHandlerCode(ev, ast.on[ev]);
3969
- const idx = block.insertData(name, "hdlr");
3970
- attrs[`block-handler-${idx}`] = ev;
3971
- }
3972
- // t-ref
3973
- if (ast.ref) {
3974
- this.target.hasRef = true;
3975
- const isDynamic = INTERP_REGEXP.test(ast.ref);
3976
- if (isDynamic) {
3977
- const str = replaceDynamicParts(ast.ref, (expr) => this.captureExpression(expr, true));
3978
- const idx = block.insertData(`(el) => refs[${str}] = el`, "ref");
3979
- attrs["block-ref"] = String(idx);
3980
- }
3981
- else {
3982
- let name = ast.ref;
3983
- if (name in this.target.refInfo) {
3984
- // ref has already been defined
3985
- this.helpers.add("multiRefSetter");
3986
- const info = this.target.refInfo[name];
3987
- const index = block.data.push(info[0]) - 1;
3988
- attrs["block-ref"] = String(index);
3989
- info[1] = `multiRefSetter(refs, \`${name}\`)`;
3990
- }
3991
- else {
3992
- let id = generateId("ref");
3993
- this.target.refInfo[name] = [id, `(el) => refs[\`${name}\`] = el`];
3994
- const index = block.data.push(id) - 1;
3995
- attrs["block-ref"] = String(index);
3996
- }
3997
- }
3998
- }
3999
4007
  // t-model
4000
4008
  let tModelSelectedExpr;
4001
4009
  if (ast.model) {
@@ -4029,6 +4037,39 @@ class CodeGenerator {
4029
4037
  idx = block.insertData(handler, "hdlr");
4030
4038
  attrs[`block-handler-${idx}`] = eventType;
4031
4039
  }
4040
+ // event handlers
4041
+ for (let ev in ast.on) {
4042
+ const name = this.generateHandlerCode(ev, ast.on[ev]);
4043
+ const idx = block.insertData(name, "hdlr");
4044
+ attrs[`block-handler-${idx}`] = ev;
4045
+ }
4046
+ // t-ref
4047
+ if (ast.ref) {
4048
+ this.target.hasRef = true;
4049
+ const isDynamic = INTERP_REGEXP.test(ast.ref);
4050
+ if (isDynamic) {
4051
+ const str = replaceDynamicParts(ast.ref, (expr) => this.captureExpression(expr, true));
4052
+ const idx = block.insertData(`(el) => refs[${str}] = el`, "ref");
4053
+ attrs["block-ref"] = String(idx);
4054
+ }
4055
+ else {
4056
+ let name = ast.ref;
4057
+ if (name in this.target.refInfo) {
4058
+ // ref has already been defined
4059
+ this.helpers.add("multiRefSetter");
4060
+ const info = this.target.refInfo[name];
4061
+ const index = block.data.push(info[0]) - 1;
4062
+ attrs["block-ref"] = String(index);
4063
+ info[1] = `multiRefSetter(refs, \`${name}\`)`;
4064
+ }
4065
+ else {
4066
+ let id = generateId("ref");
4067
+ this.target.refInfo[name] = [id, `(el) => refs[\`${name}\`] = el`];
4068
+ const index = block.data.push(id) - 1;
4069
+ attrs["block-ref"] = String(index);
4070
+ }
4071
+ }
4072
+ }
4032
4073
  const dom = xmlDoc.createElement(ast.tag);
4033
4074
  for (const [attr, val] of Object.entries(attrs)) {
4034
4075
  if (!(attr === "class" && val === "")) {
@@ -4219,8 +4260,8 @@ class CodeGenerator {
4219
4260
  if (this.dev) {
4220
4261
  // Throw error on duplicate keys in dev mode
4221
4262
  this.helpers.add("OwlError");
4222
- this.addLine(`if (keys${block.id}.has(key${this.target.loopLevel})) { throw new OwlError(\`Got duplicate key in t-foreach: \${key${this.target.loopLevel}}\`)}`);
4223
- this.addLine(`keys${block.id}.add(key${this.target.loopLevel});`);
4263
+ this.addLine(`if (keys${block.id}.has(String(key${this.target.loopLevel}))) { throw new OwlError(\`Got duplicate key in t-foreach: \${key${this.target.loopLevel}}\`)}`);
4264
+ this.addLine(`keys${block.id}.add(String(key${this.target.loopLevel}));`);
4224
4265
  }
4225
4266
  let id;
4226
4267
  if (ast.memo) {
@@ -4437,7 +4478,7 @@ class CodeGenerator {
4437
4478
  if (suffix === "bind") {
4438
4479
  this.helpers.add("bind");
4439
4480
  name = _name;
4440
- value = `bind(ctx, ${value || undefined})`;
4481
+ value = `bind(this, ${value || undefined})`;
4441
4482
  }
4442
4483
  else {
4443
4484
  throw new OwlError("Invalid prop suffix");
@@ -4468,7 +4509,7 @@ class CodeGenerator {
4468
4509
  if (this.target.loopLevel || !this.hasSafeContext) {
4469
4510
  ctxStr = generateId("ctx");
4470
4511
  this.helpers.add("capture");
4471
- this.define(ctxStr, `capture(ctx)`);
4512
+ this.define(ctxStr, `capture(ctx, this)`);
4472
4513
  }
4473
4514
  let slotStr = [];
4474
4515
  for (let slotName in ast.slots) {
@@ -4476,7 +4517,7 @@ class CodeGenerator {
4476
4517
  const params = [];
4477
4518
  if (slotAst.content) {
4478
4519
  const name = this.compileInNewTarget("slot", slotAst.content, ctx, slotAst.on);
4479
- params.push(`__render: ${name}, __ctx: ${ctxStr}`);
4520
+ params.push(`__render: ${name}.bind(this), __ctx: ${ctxStr}`);
4480
4521
  }
4481
4522
  const scope = ast.slots[slotName].scope;
4482
4523
  if (scope) {
@@ -4587,7 +4628,7 @@ class CodeGenerator {
4587
4628
  const scope = this.getPropString(props, dynProps);
4588
4629
  if (ast.defaultContent) {
4589
4630
  const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
4590
- blockString = `callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope}, ${name})`;
4631
+ blockString = `callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope}, ${name}.bind(this))`;
4591
4632
  }
4592
4633
  else {
4593
4634
  if (dynamic) {
@@ -4627,7 +4668,7 @@ class CodeGenerator {
4627
4668
  if (this.target.loopLevel || !this.hasSafeContext) {
4628
4669
  ctxStr = generateId("ctx");
4629
4670
  this.helpers.add("capture");
4630
- this.define(ctxStr, `capture(ctx)`);
4671
+ this.define(ctxStr, `capture(ctx, this)`);
4631
4672
  }
4632
4673
  let id = generateId("comp");
4633
4674
  this.staticDefs.push({
@@ -4635,7 +4676,7 @@ class CodeGenerator {
4635
4676
  expr: `app.createComponent(null, false, true, false, false)`,
4636
4677
  });
4637
4678
  const target = compileExpr(ast.target);
4638
- const blockString = `${id}({target: ${target},slots: {'default': {__render: ${name}, __ctx: ${ctxStr}}}}, key + \`${key}\`, node, ctx, Portal)`;
4679
+ const blockString = `${id}({target: ${target},slots: {'default': {__render: ${name}.bind(this), __ctx: ${ctxStr}}}}, key + \`${key}\`, node, ctx, Portal)`;
4639
4680
  if (block) {
4640
4681
  this.insertAnchor(block);
4641
4682
  }
@@ -5168,8 +5209,9 @@ function parseComponent(node, ctx) {
5168
5209
  }
5169
5210
  // default slot
5170
5211
  const defaultContent = parseChildNodes(clone, ctx);
5171
- if (defaultContent) {
5172
- slots = slots || {};
5212
+ slots = slots || {};
5213
+ // t-set-slot="default" has priority over content
5214
+ if (defaultContent && !slots.default) {
5173
5215
  slots.default = { content: defaultContent, on, attrs: null, scope: defaultSlotScope };
5174
5216
  }
5175
5217
  }
@@ -5609,7 +5651,11 @@ class App extends TemplateSet {
5609
5651
  else {
5610
5652
  // new component
5611
5653
  if (isStatic) {
5612
- C = parent.constructor.components[name];
5654
+ const components = parent.constructor.components;
5655
+ if (!components) {
5656
+ throw new OwlError(`Cannot find the definition of component "${name}", missing static components key in parent`);
5657
+ }
5658
+ C = components[name];
5613
5659
  if (!C) {
5614
5660
  throw new OwlError(`Cannot find the definition of component "${name}"`);
5615
5661
  }
@@ -5809,7 +5855,7 @@ exports.whenReady = whenReady;
5809
5855
  exports.xml = xml;
5810
5856
 
5811
5857
 
5812
- __info__.version = '2.0.0';
5813
- __info__.date = '2022-10-07T13:28:10.216Z';
5814
- __info__.hash = 'a1f2282';
5858
+ __info__.version = '2.0.2';
5859
+ __info__.date = '2022-11-29T14:11:11.260Z';
5860
+ __info__.hash = 'ef8baa2';
5815
5861
  __info__.url = 'https://github.com/odoo/owl';