@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.es.js CHANGED
@@ -1740,10 +1740,6 @@ class MountFiber extends RootFiber {
1740
1740
  }
1741
1741
  }
1742
1742
 
1743
- // Allows to get the target of a Reactive (used for making a new Reactive from the underlying object)
1744
- const TARGET = Symbol("Target");
1745
- // Escape hatch to prevent reactivity system to turn something into a reactive
1746
- const SKIP = Symbol("Skip");
1747
1743
  // Special key to subscribe to, to be notified of key creation/deletion
1748
1744
  const KEYCHANGES = Symbol("Key changes");
1749
1745
  const objectToString = Object.prototype.toString;
@@ -1760,7 +1756,7 @@ const COLLECTION_RAWTYPES = new Set(["Set", "Map", "WeakMap"]);
1760
1756
  * @returns the raw type of the object
1761
1757
  */
1762
1758
  function rawType(obj) {
1763
- return objectToString.call(obj).slice(8, -1);
1759
+ return objectToString.call(toRaw(obj)).slice(8, -1);
1764
1760
  }
1765
1761
  /**
1766
1762
  * Checks whether a given value can be made into a reactive object.
@@ -1784,6 +1780,7 @@ function canBeMadeReactive(value) {
1784
1780
  function possiblyReactive(val, cb) {
1785
1781
  return canBeMadeReactive(val) ? reactive(val, cb) : val;
1786
1782
  }
1783
+ const skipped = new WeakSet();
1787
1784
  /**
1788
1785
  * Mark an object or array so that it is ignored by the reactivity system
1789
1786
  *
@@ -1791,7 +1788,7 @@ function possiblyReactive(val, cb) {
1791
1788
  * @returns the object itself
1792
1789
  */
1793
1790
  function markRaw(value) {
1794
- value[SKIP] = true;
1791
+ skipped.add(value);
1795
1792
  return value;
1796
1793
  }
1797
1794
  /**
@@ -1801,7 +1798,7 @@ function markRaw(value) {
1801
1798
  * @returns the underlying value
1802
1799
  */
1803
1800
  function toRaw(value) {
1804
- return value[TARGET] || value;
1801
+ return targets.has(value) ? targets.get(value) : value;
1805
1802
  }
1806
1803
  const targetToKeysToCallbacks = new WeakMap();
1807
1804
  /**
@@ -1883,6 +1880,8 @@ function getSubscriptions(callback) {
1883
1880
  };
1884
1881
  });
1885
1882
  }
1883
+ // Maps reactive objects to the underlying target
1884
+ const targets = new WeakMap();
1886
1885
  const reactiveCache = new WeakMap();
1887
1886
  /**
1888
1887
  * Creates a reactive proxy for an object. Reading data on the reactive object
@@ -1898,7 +1897,7 @@ const reactiveCache = new WeakMap();
1898
1897
  * Subscriptions:
1899
1898
  * + Reading a property on an object will subscribe you to changes in the value
1900
1899
  * of that property.
1901
- * + Accessing an object keys (eg with Object.keys or with `for..in`) will
1900
+ * + Accessing an object's keys (eg with Object.keys or with `for..in`) will
1902
1901
  * subscribe you to the creation/deletion of keys. Checking the presence of a
1903
1902
  * key on the object with 'in' has the same effect.
1904
1903
  * - getOwnPropertyDescriptor does not currently subscribe you to the property.
@@ -1915,12 +1914,12 @@ function reactive(target, callback = () => { }) {
1915
1914
  if (!canBeMadeReactive(target)) {
1916
1915
  throw new OwlError(`Cannot make the given value reactive`);
1917
1916
  }
1918
- if (SKIP in target) {
1917
+ if (skipped.has(target)) {
1919
1918
  return target;
1920
1919
  }
1921
- const originalTarget = target[TARGET];
1922
- if (originalTarget) {
1923
- return reactive(originalTarget, callback);
1920
+ if (targets.has(target)) {
1921
+ // target is reactive, create a reactive on the underlying object instead
1922
+ return reactive(targets.get(target), callback);
1924
1923
  }
1925
1924
  if (!reactiveCache.has(target)) {
1926
1925
  reactiveCache.set(target, new WeakMap());
@@ -1933,6 +1932,7 @@ function reactive(target, callback = () => { }) {
1933
1932
  : basicProxyHandler(callback);
1934
1933
  const proxy = new Proxy(target, handler);
1935
1934
  reactivesForTarget.set(callback, proxy);
1935
+ targets.set(proxy, target);
1936
1936
  }
1937
1937
  return reactivesForTarget.get(callback);
1938
1938
  }
@@ -1944,29 +1944,27 @@ function reactive(target, callback = () => { }) {
1944
1944
  */
1945
1945
  function basicProxyHandler(callback) {
1946
1946
  return {
1947
- get(target, key, proxy) {
1948
- if (key === TARGET) {
1949
- return target;
1950
- }
1947
+ get(target, key, receiver) {
1951
1948
  // non-writable non-configurable properties cannot be made reactive
1952
1949
  const desc = Object.getOwnPropertyDescriptor(target, key);
1953
1950
  if (desc && !desc.writable && !desc.configurable) {
1954
- return Reflect.get(target, key, proxy);
1951
+ return Reflect.get(target, key, receiver);
1955
1952
  }
1956
1953
  observeTargetKey(target, key, callback);
1957
- return possiblyReactive(Reflect.get(target, key, proxy), callback);
1954
+ return possiblyReactive(Reflect.get(target, key, receiver), callback);
1958
1955
  },
1959
- set(target, key, value, proxy) {
1960
- const isNewKey = !objectHasOwnProperty.call(target, key);
1961
- const originalValue = Reflect.get(target, key, proxy);
1962
- const ret = Reflect.set(target, key, value, proxy);
1963
- if (isNewKey) {
1956
+ set(target, key, value, receiver) {
1957
+ const hadKey = objectHasOwnProperty.call(target, key);
1958
+ const originalValue = Reflect.get(target, key, receiver);
1959
+ const ret = Reflect.set(target, key, value, receiver);
1960
+ if (!hadKey && objectHasOwnProperty.call(target, key)) {
1964
1961
  notifyReactives(target, KEYCHANGES);
1965
1962
  }
1966
1963
  // While Array length may trigger the set trap, it's not actually set by this
1967
1964
  // method but is updated behind the scenes, and the trap is not called with the
1968
1965
  // new value. We disable the "same-value-optimization" for it because of that.
1969
- if (originalValue !== value || (Array.isArray(target) && key === "length")) {
1966
+ if (originalValue !== Reflect.get(target, key, receiver) ||
1967
+ (key === "length" && Array.isArray(target))) {
1970
1968
  notifyReactives(target, key);
1971
1969
  }
1972
1970
  return ret;
@@ -2142,10 +2140,8 @@ function collectionsProxyHandler(target, callback, targetRawType) {
2142
2140
  // property is read.
2143
2141
  const specialHandlers = rawTypeToFuncHandlers[targetRawType](target, callback);
2144
2142
  return Object.assign(basicProxyHandler(callback), {
2143
+ // FIXME: probably broken when part of prototype chain since we ignore the receiver
2145
2144
  get(target, key) {
2146
- if (key === TARGET) {
2147
- return target;
2148
- }
2149
2145
  if (objectHasOwnProperty.call(specialHandlers, key)) {
2150
2146
  return specialHandlers[key];
2151
2147
  }
@@ -2305,12 +2301,13 @@ class ComponentNode {
2305
2301
  this.childEnv = env;
2306
2302
  for (const key in props) {
2307
2303
  const prop = props[key];
2308
- if (prop && typeof prop === "object" && prop[TARGET]) {
2304
+ if (prop && typeof prop === "object" && targets.has(prop)) {
2309
2305
  props[key] = useState(prop);
2310
2306
  }
2311
2307
  }
2312
2308
  this.component = new C(props, env, this);
2313
- this.renderFn = app.getTemplate(C.template).bind(this.component, this.component, this);
2309
+ const ctx = Object.assign(Object.create(this.component), { this: this.component });
2310
+ this.renderFn = app.getTemplate(C.template).bind(this.component, ctx, this);
2314
2311
  this.component.setup();
2315
2312
  currentNode = null;
2316
2313
  }
@@ -2423,7 +2420,7 @@ class ComponentNode {
2423
2420
  currentNode = this;
2424
2421
  for (const key in props) {
2425
2422
  const prop = props[key];
2426
- if (prop && typeof prop === "object" && prop[TARGET]) {
2423
+ if (prop && typeof prop === "object" && targets.has(prop)) {
2427
2424
  props[key] = useState(prop);
2428
2425
  }
2429
2426
  }
@@ -2501,6 +2498,7 @@ class ComponentNode {
2501
2498
  }
2502
2499
  _patch() {
2503
2500
  let hasChildren = false;
2501
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2504
2502
  for (let _k in this.children) {
2505
2503
  hasChildren = true;
2506
2504
  break;
@@ -2881,7 +2879,7 @@ function callSlot(ctx, parent, key, name, dynamic, extra, defaultContent) {
2881
2879
  if (__scope) {
2882
2880
  slotScope[__scope] = extra;
2883
2881
  }
2884
- const slotBDom = __render ? __render.call(__ctx.__owl__.component, slotScope, parent, key) : null;
2882
+ const slotBDom = __render ? __render(slotScope, parent, key) : null;
2885
2883
  if (defaultContent) {
2886
2884
  let child1 = undefined;
2887
2885
  let child2 = undefined;
@@ -2889,15 +2887,14 @@ function callSlot(ctx, parent, key, name, dynamic, extra, defaultContent) {
2889
2887
  child1 = dynamic ? toggler(name, slotBDom) : slotBDom;
2890
2888
  }
2891
2889
  else {
2892
- child2 = defaultContent.call(ctx.__owl__.component, ctx, parent, key);
2890
+ child2 = defaultContent(ctx, parent, key);
2893
2891
  }
2894
2892
  return multi([child1, child2]);
2895
2893
  }
2896
2894
  return slotBDom || text("");
2897
2895
  }
2898
2896
  function capture(ctx) {
2899
- const component = ctx.__owl__.component;
2900
- const result = ObjectCreate(component);
2897
+ const result = ObjectCreate(ctx);
2901
2898
  for (let k in ctx) {
2902
2899
  result[k] = ctx[k];
2903
2900
  }
@@ -3006,8 +3003,7 @@ function safeOutput(value, defaultValue) {
3006
3003
  let boundFunctions = new WeakMap();
3007
3004
  const WeakMapGet = WeakMap.prototype.get;
3008
3005
  const WeakMapSet = WeakMap.prototype.set;
3009
- function bind(ctx, fn) {
3010
- let component = ctx.__owl__.component;
3006
+ function bind(component, fn) {
3011
3007
  let boundFnMap = WeakMapGet.call(boundFunctions, component);
3012
3008
  if (!boundFnMap) {
3013
3009
  boundFnMap = new WeakMap();
@@ -3235,7 +3231,7 @@ TemplateSet.registerTemplate("__portal__", portalTemplate);
3235
3231
  //------------------------------------------------------------------------------
3236
3232
  // Misc types, constants and helpers
3237
3233
  //------------------------------------------------------------------------------
3238
- 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(",");
3234
+ const RESERVED_WORDS = "true,false,NaN,null,undefined,debugger,console,window,in,instanceof,new,function,return,eval,void,Math,RegExp,Array,Object,Date".split(",");
3239
3235
  const WORD_REPLACEMENT = Object.assign(Object.create(null), {
3240
3236
  and: "&&",
3241
3237
  or: "||",
@@ -3621,7 +3617,7 @@ class CodeTarget {
3621
3617
  let result = [];
3622
3618
  result.push(`function ${this.name}(ctx, node, key = "") {`);
3623
3619
  if (this.hasRef) {
3624
- result.push(` const refs = ctx.__owl__.refs;`);
3620
+ result.push(` const refs = this.__owl__.refs;`);
3625
3621
  for (let name in this.refInfo) {
3626
3622
  const [id, expr] = this.refInfo[name];
3627
3623
  result.push(` const ${id} = ${expr};`);
@@ -3713,7 +3709,7 @@ class CodeGenerator {
3713
3709
  for (let block of this.blocks) {
3714
3710
  if (block.dom) {
3715
3711
  let xmlString = block.asXmlString();
3716
- xmlString = xmlString.replace(/`/g, "\\`");
3712
+ xmlString = xmlString.replace(/\\/g, "\\\\").replace(/`/g, "\\`");
3717
3713
  if (block.dynamicTagName) {
3718
3714
  xmlString = xmlString.replace(/^<\w+/, `<\${tag || '${block.dom.nodeName}'}`);
3719
3715
  xmlString = xmlString.replace(/\w+>$/, `\${tag || '${block.dom.nodeName}'}>`);
@@ -4006,39 +4002,6 @@ class CodeGenerator {
4006
4002
  attrs[`block-attribute-${selectedId}`] = "selected";
4007
4003
  }
4008
4004
  }
4009
- // event handlers
4010
- for (let ev in ast.on) {
4011
- const name = this.generateHandlerCode(ev, ast.on[ev]);
4012
- const idx = block.insertData(name, "hdlr");
4013
- attrs[`block-handler-${idx}`] = ev;
4014
- }
4015
- // t-ref
4016
- if (ast.ref) {
4017
- this.target.hasRef = true;
4018
- const isDynamic = INTERP_REGEXP.test(ast.ref);
4019
- if (isDynamic) {
4020
- const str = replaceDynamicParts(ast.ref, (expr) => this.captureExpression(expr, true));
4021
- const idx = block.insertData(`(el) => refs[${str}] = el`, "ref");
4022
- attrs["block-ref"] = String(idx);
4023
- }
4024
- else {
4025
- let name = ast.ref;
4026
- if (name in this.target.refInfo) {
4027
- // ref has already been defined
4028
- this.helpers.add("multiRefSetter");
4029
- const info = this.target.refInfo[name];
4030
- const index = block.data.push(info[0]) - 1;
4031
- attrs["block-ref"] = String(index);
4032
- info[1] = `multiRefSetter(refs, \`${name}\`)`;
4033
- }
4034
- else {
4035
- let id = generateId("ref");
4036
- this.target.refInfo[name] = [id, `(el) => refs[\`${name}\`] = el`];
4037
- const index = block.data.push(id) - 1;
4038
- attrs["block-ref"] = String(index);
4039
- }
4040
- }
4041
- }
4042
4005
  // t-model
4043
4006
  let tModelSelectedExpr;
4044
4007
  if (ast.model) {
@@ -4072,6 +4035,39 @@ class CodeGenerator {
4072
4035
  idx = block.insertData(handler, "hdlr");
4073
4036
  attrs[`block-handler-${idx}`] = eventType;
4074
4037
  }
4038
+ // event handlers
4039
+ for (let ev in ast.on) {
4040
+ const name = this.generateHandlerCode(ev, ast.on[ev]);
4041
+ const idx = block.insertData(name, "hdlr");
4042
+ attrs[`block-handler-${idx}`] = ev;
4043
+ }
4044
+ // t-ref
4045
+ if (ast.ref) {
4046
+ this.target.hasRef = true;
4047
+ const isDynamic = INTERP_REGEXP.test(ast.ref);
4048
+ if (isDynamic) {
4049
+ const str = replaceDynamicParts(ast.ref, (expr) => this.captureExpression(expr, true));
4050
+ const idx = block.insertData(`(el) => refs[${str}] = el`, "ref");
4051
+ attrs["block-ref"] = String(idx);
4052
+ }
4053
+ else {
4054
+ let name = ast.ref;
4055
+ if (name in this.target.refInfo) {
4056
+ // ref has already been defined
4057
+ this.helpers.add("multiRefSetter");
4058
+ const info = this.target.refInfo[name];
4059
+ const index = block.data.push(info[0]) - 1;
4060
+ attrs["block-ref"] = String(index);
4061
+ info[1] = `multiRefSetter(refs, \`${name}\`)`;
4062
+ }
4063
+ else {
4064
+ let id = generateId("ref");
4065
+ this.target.refInfo[name] = [id, `(el) => refs[\`${name}\`] = el`];
4066
+ const index = block.data.push(id) - 1;
4067
+ attrs["block-ref"] = String(index);
4068
+ }
4069
+ }
4070
+ }
4075
4071
  const dom = xmlDoc.createElement(ast.tag);
4076
4072
  for (const [attr, val] of Object.entries(attrs)) {
4077
4073
  if (!(attr === "class" && val === "")) {
@@ -4480,7 +4476,7 @@ class CodeGenerator {
4480
4476
  if (suffix === "bind") {
4481
4477
  this.helpers.add("bind");
4482
4478
  name = _name;
4483
- value = `bind(ctx, ${value || undefined})`;
4479
+ value = `bind(this, ${value || undefined})`;
4484
4480
  }
4485
4481
  else {
4486
4482
  throw new OwlError("Invalid prop suffix");
@@ -4519,7 +4515,7 @@ class CodeGenerator {
4519
4515
  const params = [];
4520
4516
  if (slotAst.content) {
4521
4517
  const name = this.compileInNewTarget("slot", slotAst.content, ctx, slotAst.on);
4522
- params.push(`__render: ${name}, __ctx: ${ctxStr}`);
4518
+ params.push(`__render: ${name}.bind(this), __ctx: ${ctxStr}`);
4523
4519
  }
4524
4520
  const scope = ast.slots[slotName].scope;
4525
4521
  if (scope) {
@@ -4630,7 +4626,7 @@ class CodeGenerator {
4630
4626
  const scope = this.getPropString(props, dynProps);
4631
4627
  if (ast.defaultContent) {
4632
4628
  const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
4633
- blockString = `callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope}, ${name})`;
4629
+ blockString = `callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope}, ${name}.bind(this))`;
4634
4630
  }
4635
4631
  else {
4636
4632
  if (dynamic) {
@@ -4678,7 +4674,7 @@ class CodeGenerator {
4678
4674
  expr: `app.createComponent(null, false, true, false, false)`,
4679
4675
  });
4680
4676
  const target = compileExpr(ast.target);
4681
- const blockString = `${id}({target: ${target},slots: {'default': {__render: ${name}, __ctx: ${ctxStr}}}}, key + \`${key}\`, node, ctx, Portal)`;
4677
+ const blockString = `${id}({target: ${target},slots: {'default': {__render: ${name}.bind(this), __ctx: ${ctxStr}}}}, key + \`${key}\`, node, ctx, Portal)`;
4682
4678
  if (block) {
4683
4679
  this.insertAnchor(block);
4684
4680
  }
@@ -5653,7 +5649,11 @@ class App extends TemplateSet {
5653
5649
  else {
5654
5650
  // new component
5655
5651
  if (isStatic) {
5656
- C = parent.constructor.components[name];
5652
+ const components = parent.constructor.components;
5653
+ if (!components) {
5654
+ throw new OwlError(`Cannot find the definition of component "${name}", missing static components key in parent`);
5655
+ }
5656
+ C = components[name];
5657
5657
  if (!C) {
5658
5658
  throw new OwlError(`Cannot find the definition of component "${name}"`);
5659
5659
  }
@@ -5820,7 +5820,7 @@ TemplateSet.prototype._compileTemplate = function _compileTemplate(name, templat
5820
5820
  export { App, Component, EventBus, OwlError, __info__, blockDom, loadFile, markRaw, markup, mount, onError, onMounted, onPatched, onRendered, onWillDestroy, onWillPatch, onWillRender, onWillStart, onWillUnmount, onWillUpdateProps, reactive, status, toRaw, useChildSubEnv, useComponent, useEffect, useEnv, useExternalListener, useRef, useState, useSubEnv, validate, whenReady, xml };
5821
5821
 
5822
5822
 
5823
- __info__.version = '2.0.1';
5824
- __info__.date = '2022-10-21T08:41:01.873Z';
5825
- __info__.hash = '9fe8e93';
5823
+ __info__.version = '2.0.3';
5824
+ __info__.date = '2023-01-20T10:27:02.171Z';
5825
+ __info__.hash = '316eb06';
5826
5826
  __info__.url = 'https://github.com/odoo/owl';