@odoo/owl 2.0.1 → 2.0.3

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;
@@ -1764,7 +1760,7 @@ const COLLECTION_RAWTYPES = new Set(["Set", "Map", "WeakMap"]);
1764
1760
  * @returns the raw type of the object
1765
1761
  */
1766
1762
  function rawType(obj) {
1767
- return objectToString.call(obj).slice(8, -1);
1763
+ return objectToString.call(toRaw(obj)).slice(8, -1);
1768
1764
  }
1769
1765
  /**
1770
1766
  * Checks whether a given value can be made into a reactive object.
@@ -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,12 +2305,13 @@ 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
  }
2316
2312
  this.component = new C(props, env, this);
2317
- this.renderFn = app.getTemplate(C.template).bind(this.component, this.component, this);
2313
+ const ctx = Object.assign(Object.create(this.component), { this: this.component });
2314
+ this.renderFn = app.getTemplate(C.template).bind(this.component, ctx, this);
2318
2315
  this.component.setup();
2319
2316
  currentNode = null;
2320
2317
  }
@@ -2427,7 +2424,7 @@ class ComponentNode {
2427
2424
  currentNode = this;
2428
2425
  for (const key in props) {
2429
2426
  const prop = props[key];
2430
- if (prop && typeof prop === "object" && prop[TARGET]) {
2427
+ if (prop && typeof prop === "object" && targets.has(prop)) {
2431
2428
  props[key] = useState(prop);
2432
2429
  }
2433
2430
  }
@@ -2505,6 +2502,7 @@ class ComponentNode {
2505
2502
  }
2506
2503
  _patch() {
2507
2504
  let hasChildren = false;
2505
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2508
2506
  for (let _k in this.children) {
2509
2507
  hasChildren = true;
2510
2508
  break;
@@ -2885,7 +2883,7 @@ function callSlot(ctx, parent, key, name, dynamic, extra, defaultContent) {
2885
2883
  if (__scope) {
2886
2884
  slotScope[__scope] = extra;
2887
2885
  }
2888
- const slotBDom = __render ? __render.call(__ctx.__owl__.component, slotScope, parent, key) : null;
2886
+ const slotBDom = __render ? __render(slotScope, parent, key) : null;
2889
2887
  if (defaultContent) {
2890
2888
  let child1 = undefined;
2891
2889
  let child2 = undefined;
@@ -2893,15 +2891,14 @@ function callSlot(ctx, parent, key, name, dynamic, extra, defaultContent) {
2893
2891
  child1 = dynamic ? toggler(name, slotBDom) : slotBDom;
2894
2892
  }
2895
2893
  else {
2896
- child2 = defaultContent.call(ctx.__owl__.component, ctx, parent, key);
2894
+ child2 = defaultContent(ctx, parent, key);
2897
2895
  }
2898
2896
  return multi([child1, child2]);
2899
2897
  }
2900
2898
  return slotBDom || text("");
2901
2899
  }
2902
2900
  function capture(ctx) {
2903
- const component = ctx.__owl__.component;
2904
- const result = ObjectCreate(component);
2901
+ const result = ObjectCreate(ctx);
2905
2902
  for (let k in ctx) {
2906
2903
  result[k] = ctx[k];
2907
2904
  }
@@ -3010,8 +3007,7 @@ function safeOutput(value, defaultValue) {
3010
3007
  let boundFunctions = new WeakMap();
3011
3008
  const WeakMapGet = WeakMap.prototype.get;
3012
3009
  const WeakMapSet = WeakMap.prototype.set;
3013
- function bind(ctx, fn) {
3014
- let component = ctx.__owl__.component;
3010
+ function bind(component, fn) {
3015
3011
  let boundFnMap = WeakMapGet.call(boundFunctions, component);
3016
3012
  if (!boundFnMap) {
3017
3013
  boundFnMap = new WeakMap();
@@ -3239,7 +3235,7 @@ TemplateSet.registerTemplate("__portal__", portalTemplate);
3239
3235
  //------------------------------------------------------------------------------
3240
3236
  // Misc types, constants and helpers
3241
3237
  //------------------------------------------------------------------------------
3242
- const RESERVED_WORDS = "true,false,NaN,null,undefined,debugger,console,window,in,instanceof,new,function,return,this,eval,void,Math,RegExp,Array,Object,Date".split(",");
3238
+ const RESERVED_WORDS = "true,false,NaN,null,undefined,debugger,console,window,in,instanceof,new,function,return,eval,void,Math,RegExp,Array,Object,Date".split(",");
3243
3239
  const WORD_REPLACEMENT = Object.assign(Object.create(null), {
3244
3240
  and: "&&",
3245
3241
  or: "||",
@@ -3625,7 +3621,7 @@ class CodeTarget {
3625
3621
  let result = [];
3626
3622
  result.push(`function ${this.name}(ctx, node, key = "") {`);
3627
3623
  if (this.hasRef) {
3628
- result.push(` const refs = ctx.__owl__.refs;`);
3624
+ result.push(` const refs = this.__owl__.refs;`);
3629
3625
  for (let name in this.refInfo) {
3630
3626
  const [id, expr] = this.refInfo[name];
3631
3627
  result.push(` const ${id} = ${expr};`);
@@ -3717,7 +3713,7 @@ class CodeGenerator {
3717
3713
  for (let block of this.blocks) {
3718
3714
  if (block.dom) {
3719
3715
  let xmlString = block.asXmlString();
3720
- xmlString = xmlString.replace(/`/g, "\\`");
3716
+ xmlString = xmlString.replace(/\\/g, "\\\\").replace(/`/g, "\\`");
3721
3717
  if (block.dynamicTagName) {
3722
3718
  xmlString = xmlString.replace(/^<\w+/, `<\${tag || '${block.dom.nodeName}'}`);
3723
3719
  xmlString = xmlString.replace(/\w+>$/, `\${tag || '${block.dom.nodeName}'}>`);
@@ -4010,39 +4006,6 @@ class CodeGenerator {
4010
4006
  attrs[`block-attribute-${selectedId}`] = "selected";
4011
4007
  }
4012
4008
  }
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
4009
  // t-model
4047
4010
  let tModelSelectedExpr;
4048
4011
  if (ast.model) {
@@ -4076,6 +4039,39 @@ class CodeGenerator {
4076
4039
  idx = block.insertData(handler, "hdlr");
4077
4040
  attrs[`block-handler-${idx}`] = eventType;
4078
4041
  }
4042
+ // event handlers
4043
+ for (let ev in ast.on) {
4044
+ const name = this.generateHandlerCode(ev, ast.on[ev]);
4045
+ const idx = block.insertData(name, "hdlr");
4046
+ attrs[`block-handler-${idx}`] = ev;
4047
+ }
4048
+ // t-ref
4049
+ if (ast.ref) {
4050
+ this.target.hasRef = true;
4051
+ const isDynamic = INTERP_REGEXP.test(ast.ref);
4052
+ if (isDynamic) {
4053
+ const str = replaceDynamicParts(ast.ref, (expr) => this.captureExpression(expr, true));
4054
+ const idx = block.insertData(`(el) => refs[${str}] = el`, "ref");
4055
+ attrs["block-ref"] = String(idx);
4056
+ }
4057
+ else {
4058
+ let name = ast.ref;
4059
+ if (name in this.target.refInfo) {
4060
+ // ref has already been defined
4061
+ this.helpers.add("multiRefSetter");
4062
+ const info = this.target.refInfo[name];
4063
+ const index = block.data.push(info[0]) - 1;
4064
+ attrs["block-ref"] = String(index);
4065
+ info[1] = `multiRefSetter(refs, \`${name}\`)`;
4066
+ }
4067
+ else {
4068
+ let id = generateId("ref");
4069
+ this.target.refInfo[name] = [id, `(el) => refs[\`${name}\`] = el`];
4070
+ const index = block.data.push(id) - 1;
4071
+ attrs["block-ref"] = String(index);
4072
+ }
4073
+ }
4074
+ }
4079
4075
  const dom = xmlDoc.createElement(ast.tag);
4080
4076
  for (const [attr, val] of Object.entries(attrs)) {
4081
4077
  if (!(attr === "class" && val === "")) {
@@ -4484,7 +4480,7 @@ class CodeGenerator {
4484
4480
  if (suffix === "bind") {
4485
4481
  this.helpers.add("bind");
4486
4482
  name = _name;
4487
- value = `bind(ctx, ${value || undefined})`;
4483
+ value = `bind(this, ${value || undefined})`;
4488
4484
  }
4489
4485
  else {
4490
4486
  throw new OwlError("Invalid prop suffix");
@@ -4523,7 +4519,7 @@ class CodeGenerator {
4523
4519
  const params = [];
4524
4520
  if (slotAst.content) {
4525
4521
  const name = this.compileInNewTarget("slot", slotAst.content, ctx, slotAst.on);
4526
- params.push(`__render: ${name}, __ctx: ${ctxStr}`);
4522
+ params.push(`__render: ${name}.bind(this), __ctx: ${ctxStr}`);
4527
4523
  }
4528
4524
  const scope = ast.slots[slotName].scope;
4529
4525
  if (scope) {
@@ -4634,7 +4630,7 @@ class CodeGenerator {
4634
4630
  const scope = this.getPropString(props, dynProps);
4635
4631
  if (ast.defaultContent) {
4636
4632
  const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
4637
- blockString = `callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope}, ${name})`;
4633
+ blockString = `callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope}, ${name}.bind(this))`;
4638
4634
  }
4639
4635
  else {
4640
4636
  if (dynamic) {
@@ -4682,7 +4678,7 @@ class CodeGenerator {
4682
4678
  expr: `app.createComponent(null, false, true, false, false)`,
4683
4679
  });
4684
4680
  const target = compileExpr(ast.target);
4685
- const blockString = `${id}({target: ${target},slots: {'default': {__render: ${name}, __ctx: ${ctxStr}}}}, key + \`${key}\`, node, ctx, Portal)`;
4681
+ const blockString = `${id}({target: ${target},slots: {'default': {__render: ${name}.bind(this), __ctx: ${ctxStr}}}}, key + \`${key}\`, node, ctx, Portal)`;
4686
4682
  if (block) {
4687
4683
  this.insertAnchor(block);
4688
4684
  }
@@ -5657,7 +5653,11 @@ class App extends TemplateSet {
5657
5653
  else {
5658
5654
  // new component
5659
5655
  if (isStatic) {
5660
- C = parent.constructor.components[name];
5656
+ const components = parent.constructor.components;
5657
+ if (!components) {
5658
+ throw new OwlError(`Cannot find the definition of component "${name}", missing static components key in parent`);
5659
+ }
5660
+ C = components[name];
5661
5661
  if (!C) {
5662
5662
  throw new OwlError(`Cannot find the definition of component "${name}"`);
5663
5663
  }
@@ -5857,7 +5857,7 @@ exports.whenReady = whenReady;
5857
5857
  exports.xml = xml;
5858
5858
 
5859
5859
 
5860
- __info__.version = '2.0.1';
5861
- __info__.date = '2022-10-21T08:41:01.873Z';
5862
- __info__.hash = '9fe8e93';
5860
+ __info__.version = '2.0.3';
5861
+ __info__.date = '2023-01-20T10:27:02.171Z';
5862
+ __info__.hash = '316eb06';
5863
5863
  __info__.url = 'https://github.com/odoo/owl';