@odoo/owl 2.0.1 → 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
@@ -1744,10 +1744,6 @@ class MountFiber extends RootFiber {
1744
1744
  }
1745
1745
  }
1746
1746
 
1747
- // Allows to get the target of a Reactive (used for making a new Reactive from the underlying object)
1748
- const TARGET = Symbol("Target");
1749
- // Escape hatch to prevent reactivity system to turn something into a reactive
1750
- const SKIP = Symbol("Skip");
1751
1747
  // Special key to subscribe to, to be notified of key creation/deletion
1752
1748
  const KEYCHANGES = Symbol("Key changes");
1753
1749
  const objectToString = Object.prototype.toString;
@@ -1788,6 +1784,7 @@ function canBeMadeReactive(value) {
1788
1784
  function possiblyReactive(val, cb) {
1789
1785
  return canBeMadeReactive(val) ? reactive(val, cb) : val;
1790
1786
  }
1787
+ const skipped = new WeakSet();
1791
1788
  /**
1792
1789
  * Mark an object or array so that it is ignored by the reactivity system
1793
1790
  *
@@ -1795,7 +1792,7 @@ function possiblyReactive(val, cb) {
1795
1792
  * @returns the object itself
1796
1793
  */
1797
1794
  function markRaw(value) {
1798
- value[SKIP] = true;
1795
+ skipped.add(value);
1799
1796
  return value;
1800
1797
  }
1801
1798
  /**
@@ -1805,7 +1802,7 @@ function markRaw(value) {
1805
1802
  * @returns the underlying value
1806
1803
  */
1807
1804
  function toRaw(value) {
1808
- return value[TARGET] || value;
1805
+ return targets.has(value) ? targets.get(value) : value;
1809
1806
  }
1810
1807
  const targetToKeysToCallbacks = new WeakMap();
1811
1808
  /**
@@ -1887,6 +1884,8 @@ function getSubscriptions(callback) {
1887
1884
  };
1888
1885
  });
1889
1886
  }
1887
+ // Maps reactive objects to the underlying target
1888
+ const targets = new WeakMap();
1890
1889
  const reactiveCache = new WeakMap();
1891
1890
  /**
1892
1891
  * Creates a reactive proxy for an object. Reading data on the reactive object
@@ -1902,7 +1901,7 @@ const reactiveCache = new WeakMap();
1902
1901
  * Subscriptions:
1903
1902
  * + Reading a property on an object will subscribe you to changes in the value
1904
1903
  * of that property.
1905
- * + 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
1906
1905
  * subscribe you to the creation/deletion of keys. Checking the presence of a
1907
1906
  * key on the object with 'in' has the same effect.
1908
1907
  * - getOwnPropertyDescriptor does not currently subscribe you to the property.
@@ -1919,12 +1918,12 @@ function reactive(target, callback = () => { }) {
1919
1918
  if (!canBeMadeReactive(target)) {
1920
1919
  throw new OwlError(`Cannot make the given value reactive`);
1921
1920
  }
1922
- if (SKIP in target) {
1921
+ if (skipped.has(target)) {
1923
1922
  return target;
1924
1923
  }
1925
- const originalTarget = target[TARGET];
1926
- if (originalTarget) {
1927
- 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);
1928
1927
  }
1929
1928
  if (!reactiveCache.has(target)) {
1930
1929
  reactiveCache.set(target, new WeakMap());
@@ -1937,6 +1936,7 @@ function reactive(target, callback = () => { }) {
1937
1936
  : basicProxyHandler(callback);
1938
1937
  const proxy = new Proxy(target, handler);
1939
1938
  reactivesForTarget.set(callback, proxy);
1939
+ targets.set(proxy, target);
1940
1940
  }
1941
1941
  return reactivesForTarget.get(callback);
1942
1942
  }
@@ -1948,29 +1948,27 @@ function reactive(target, callback = () => { }) {
1948
1948
  */
1949
1949
  function basicProxyHandler(callback) {
1950
1950
  return {
1951
- get(target, key, proxy) {
1952
- if (key === TARGET) {
1953
- return target;
1954
- }
1951
+ get(target, key, receiver) {
1955
1952
  // non-writable non-configurable properties cannot be made reactive
1956
1953
  const desc = Object.getOwnPropertyDescriptor(target, key);
1957
1954
  if (desc && !desc.writable && !desc.configurable) {
1958
- return Reflect.get(target, key, proxy);
1955
+ return Reflect.get(target, key, receiver);
1959
1956
  }
1960
1957
  observeTargetKey(target, key, callback);
1961
- return possiblyReactive(Reflect.get(target, key, proxy), callback);
1958
+ return possiblyReactive(Reflect.get(target, key, receiver), callback);
1962
1959
  },
1963
- set(target, key, value, proxy) {
1964
- const isNewKey = !objectHasOwnProperty.call(target, key);
1965
- const originalValue = Reflect.get(target, key, proxy);
1966
- const ret = Reflect.set(target, key, value, proxy);
1967
- 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)) {
1968
1965
  notifyReactives(target, KEYCHANGES);
1969
1966
  }
1970
1967
  // While Array length may trigger the set trap, it's not actually set by this
1971
1968
  // method but is updated behind the scenes, and the trap is not called with the
1972
1969
  // new value. We disable the "same-value-optimization" for it because of that.
1973
- if (originalValue !== value || (Array.isArray(target) && key === "length")) {
1970
+ if (originalValue !== Reflect.get(target, key, receiver) ||
1971
+ (key === "length" && Array.isArray(target))) {
1974
1972
  notifyReactives(target, key);
1975
1973
  }
1976
1974
  return ret;
@@ -2146,10 +2144,8 @@ function collectionsProxyHandler(target, callback, targetRawType) {
2146
2144
  // property is read.
2147
2145
  const specialHandlers = rawTypeToFuncHandlers[targetRawType](target, callback);
2148
2146
  return Object.assign(basicProxyHandler(callback), {
2147
+ // FIXME: probably broken when part of prototype chain since we ignore the receiver
2149
2148
  get(target, key) {
2150
- if (key === TARGET) {
2151
- return target;
2152
- }
2153
2149
  if (objectHasOwnProperty.call(specialHandlers, key)) {
2154
2150
  return specialHandlers[key];
2155
2151
  }
@@ -2309,7 +2305,7 @@ class ComponentNode {
2309
2305
  this.childEnv = env;
2310
2306
  for (const key in props) {
2311
2307
  const prop = props[key];
2312
- if (prop && typeof prop === "object" && prop[TARGET]) {
2308
+ if (prop && typeof prop === "object" && targets.has(prop)) {
2313
2309
  props[key] = useState(prop);
2314
2310
  }
2315
2311
  }
@@ -2427,7 +2423,7 @@ class ComponentNode {
2427
2423
  currentNode = this;
2428
2424
  for (const key in props) {
2429
2425
  const prop = props[key];
2430
- if (prop && typeof prop === "object" && prop[TARGET]) {
2426
+ if (prop && typeof prop === "object" && targets.has(prop)) {
2431
2427
  props[key] = useState(prop);
2432
2428
  }
2433
2429
  }
@@ -2885,7 +2881,7 @@ function callSlot(ctx, parent, key, name, dynamic, extra, defaultContent) {
2885
2881
  if (__scope) {
2886
2882
  slotScope[__scope] = extra;
2887
2883
  }
2888
- const slotBDom = __render ? __render.call(__ctx.__owl__.component, slotScope, parent, key) : null;
2884
+ const slotBDom = __render ? __render(slotScope, parent, key) : null;
2889
2885
  if (defaultContent) {
2890
2886
  let child1 = undefined;
2891
2887
  let child2 = undefined;
@@ -2893,14 +2889,13 @@ function callSlot(ctx, parent, key, name, dynamic, extra, defaultContent) {
2893
2889
  child1 = dynamic ? toggler(name, slotBDom) : slotBDom;
2894
2890
  }
2895
2891
  else {
2896
- child2 = defaultContent.call(ctx.__owl__.component, ctx, parent, key);
2892
+ child2 = defaultContent(ctx, parent, key);
2897
2893
  }
2898
2894
  return multi([child1, child2]);
2899
2895
  }
2900
2896
  return slotBDom || text("");
2901
2897
  }
2902
- function capture(ctx) {
2903
- const component = ctx.__owl__.component;
2898
+ function capture(ctx, component) {
2904
2899
  const result = ObjectCreate(component);
2905
2900
  for (let k in ctx) {
2906
2901
  result[k] = ctx[k];
@@ -2956,7 +2951,7 @@ function shallowEqual(l1, l2) {
2956
2951
  class LazyValue {
2957
2952
  constructor(fn, ctx, component, node, key) {
2958
2953
  this.fn = fn;
2959
- this.ctx = capture(ctx);
2954
+ this.ctx = capture(ctx, component);
2960
2955
  this.component = component;
2961
2956
  this.node = node;
2962
2957
  this.key = key;
@@ -3010,8 +3005,7 @@ function safeOutput(value, defaultValue) {
3010
3005
  let boundFunctions = new WeakMap();
3011
3006
  const WeakMapGet = WeakMap.prototype.get;
3012
3007
  const WeakMapSet = WeakMap.prototype.set;
3013
- function bind(ctx, fn) {
3014
- let component = ctx.__owl__.component;
3008
+ function bind(component, fn) {
3015
3009
  let boundFnMap = WeakMapGet.call(boundFunctions, component);
3016
3010
  if (!boundFnMap) {
3017
3011
  boundFnMap = new WeakMap();
@@ -3625,7 +3619,7 @@ class CodeTarget {
3625
3619
  let result = [];
3626
3620
  result.push(`function ${this.name}(ctx, node, key = "") {`);
3627
3621
  if (this.hasRef) {
3628
- result.push(` const refs = ctx.__owl__.refs;`);
3622
+ result.push(` const refs = this.__owl__.refs;`);
3629
3623
  for (let name in this.refInfo) {
3630
3624
  const [id, expr] = this.refInfo[name];
3631
3625
  result.push(` const ${id} = ${expr};`);
@@ -4010,39 +4004,6 @@ class CodeGenerator {
4010
4004
  attrs[`block-attribute-${selectedId}`] = "selected";
4011
4005
  }
4012
4006
  }
4013
- // event handlers
4014
- for (let ev in ast.on) {
4015
- const name = this.generateHandlerCode(ev, ast.on[ev]);
4016
- const idx = block.insertData(name, "hdlr");
4017
- attrs[`block-handler-${idx}`] = ev;
4018
- }
4019
- // t-ref
4020
- if (ast.ref) {
4021
- this.target.hasRef = true;
4022
- const isDynamic = INTERP_REGEXP.test(ast.ref);
4023
- if (isDynamic) {
4024
- const str = replaceDynamicParts(ast.ref, (expr) => this.captureExpression(expr, true));
4025
- const idx = block.insertData(`(el) => refs[${str}] = el`, "ref");
4026
- attrs["block-ref"] = String(idx);
4027
- }
4028
- else {
4029
- let name = ast.ref;
4030
- if (name in this.target.refInfo) {
4031
- // ref has already been defined
4032
- this.helpers.add("multiRefSetter");
4033
- const info = this.target.refInfo[name];
4034
- const index = block.data.push(info[0]) - 1;
4035
- attrs["block-ref"] = String(index);
4036
- info[1] = `multiRefSetter(refs, \`${name}\`)`;
4037
- }
4038
- else {
4039
- let id = generateId("ref");
4040
- this.target.refInfo[name] = [id, `(el) => refs[\`${name}\`] = el`];
4041
- const index = block.data.push(id) - 1;
4042
- attrs["block-ref"] = String(index);
4043
- }
4044
- }
4045
- }
4046
4007
  // t-model
4047
4008
  let tModelSelectedExpr;
4048
4009
  if (ast.model) {
@@ -4076,6 +4037,39 @@ class CodeGenerator {
4076
4037
  idx = block.insertData(handler, "hdlr");
4077
4038
  attrs[`block-handler-${idx}`] = eventType;
4078
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
+ }
4079
4073
  const dom = xmlDoc.createElement(ast.tag);
4080
4074
  for (const [attr, val] of Object.entries(attrs)) {
4081
4075
  if (!(attr === "class" && val === "")) {
@@ -4484,7 +4478,7 @@ class CodeGenerator {
4484
4478
  if (suffix === "bind") {
4485
4479
  this.helpers.add("bind");
4486
4480
  name = _name;
4487
- value = `bind(ctx, ${value || undefined})`;
4481
+ value = `bind(this, ${value || undefined})`;
4488
4482
  }
4489
4483
  else {
4490
4484
  throw new OwlError("Invalid prop suffix");
@@ -4515,7 +4509,7 @@ class CodeGenerator {
4515
4509
  if (this.target.loopLevel || !this.hasSafeContext) {
4516
4510
  ctxStr = generateId("ctx");
4517
4511
  this.helpers.add("capture");
4518
- this.define(ctxStr, `capture(ctx)`);
4512
+ this.define(ctxStr, `capture(ctx, this)`);
4519
4513
  }
4520
4514
  let slotStr = [];
4521
4515
  for (let slotName in ast.slots) {
@@ -4523,7 +4517,7 @@ class CodeGenerator {
4523
4517
  const params = [];
4524
4518
  if (slotAst.content) {
4525
4519
  const name = this.compileInNewTarget("slot", slotAst.content, ctx, slotAst.on);
4526
- params.push(`__render: ${name}, __ctx: ${ctxStr}`);
4520
+ params.push(`__render: ${name}.bind(this), __ctx: ${ctxStr}`);
4527
4521
  }
4528
4522
  const scope = ast.slots[slotName].scope;
4529
4523
  if (scope) {
@@ -4634,7 +4628,7 @@ class CodeGenerator {
4634
4628
  const scope = this.getPropString(props, dynProps);
4635
4629
  if (ast.defaultContent) {
4636
4630
  const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
4637
- blockString = `callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope}, ${name})`;
4631
+ blockString = `callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope}, ${name}.bind(this))`;
4638
4632
  }
4639
4633
  else {
4640
4634
  if (dynamic) {
@@ -4674,7 +4668,7 @@ class CodeGenerator {
4674
4668
  if (this.target.loopLevel || !this.hasSafeContext) {
4675
4669
  ctxStr = generateId("ctx");
4676
4670
  this.helpers.add("capture");
4677
- this.define(ctxStr, `capture(ctx)`);
4671
+ this.define(ctxStr, `capture(ctx, this)`);
4678
4672
  }
4679
4673
  let id = generateId("comp");
4680
4674
  this.staticDefs.push({
@@ -4682,7 +4676,7 @@ class CodeGenerator {
4682
4676
  expr: `app.createComponent(null, false, true, false, false)`,
4683
4677
  });
4684
4678
  const target = compileExpr(ast.target);
4685
- 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)`;
4686
4680
  if (block) {
4687
4681
  this.insertAnchor(block);
4688
4682
  }
@@ -5657,7 +5651,11 @@ class App extends TemplateSet {
5657
5651
  else {
5658
5652
  // new component
5659
5653
  if (isStatic) {
5660
- 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];
5661
5659
  if (!C) {
5662
5660
  throw new OwlError(`Cannot find the definition of component "${name}"`);
5663
5661
  }
@@ -5857,7 +5855,7 @@ exports.whenReady = whenReady;
5857
5855
  exports.xml = xml;
5858
5856
 
5859
5857
 
5860
- __info__.version = '2.0.1';
5861
- __info__.date = '2022-10-21T08:41:01.873Z';
5862
- __info__.hash = '9fe8e93';
5858
+ __info__.version = '2.0.2';
5859
+ __info__.date = '2022-11-29T14:11:11.260Z';
5860
+ __info__.hash = 'ef8baa2';
5863
5861
  __info__.url = 'https://github.com/odoo/owl';