@odoo/owl 2.8.1 → 3.0.0-alpha.1
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-devtools.zip +0 -0
- package/dist/owl.cjs.js +579 -182
- package/dist/owl.es.js +572 -183
- package/dist/owl.iife.js +579 -182
- package/dist/owl.iife.min.js +1 -1
- package/dist/types/common/types.d.ts +28 -0
- package/dist/types/owl.d.ts +162 -74
- package/dist/types/runtime/app.d.ts +3 -0
- package/dist/types/runtime/cancellableContext.d.ts +15 -0
- package/dist/types/runtime/cancellablePromise.d.ts +15 -0
- package/dist/types/runtime/component.d.ts +5 -0
- package/dist/types/runtime/component_node.d.ts +4 -2
- package/dist/types/runtime/executionContext.d.ts +0 -0
- package/dist/types/runtime/index.d.ts +3 -0
- package/dist/types/runtime/listOperation.d.ts +1 -0
- package/dist/types/runtime/plugins.d.ts +39 -0
- package/dist/types/runtime/reactivity.d.ts +1 -12
- package/dist/types/runtime/registry.d.ts +15 -0
- package/dist/types/runtime/relationalModel/discussModel.d.ts +19 -0
- package/dist/types/runtime/relationalModel/discussModelTypes.d.ts +22 -0
- package/dist/types/runtime/relationalModel/field.d.ts +20 -0
- package/dist/types/runtime/relationalModel/model.d.ts +59 -0
- package/dist/types/runtime/relationalModel/modelData.d.ts +18 -0
- package/dist/types/runtime/relationalModel/modelRegistry.d.ts +3 -0
- package/dist/types/runtime/relationalModel/modelUtils.d.ts +4 -0
- package/dist/types/runtime/relationalModel/store.d.ts +16 -0
- package/dist/types/runtime/relationalModel/types.d.ts +83 -0
- package/dist/types/runtime/relationalModel/util.d.ts +1 -0
- package/dist/types/runtime/relationalModel/web/WebDataPoint.d.ts +25 -0
- package/dist/types/runtime/relationalModel/web/WebRecord.d.ts +131 -0
- package/dist/types/runtime/relationalModel/web/WebStaticList.d.ts +63 -0
- package/dist/types/runtime/relationalModel/web/webModel.d.ts +5 -0
- package/dist/types/runtime/relationalModel/web/webModelTypes.d.ts +139 -0
- package/dist/types/runtime/signals.d.ts +17 -0
- package/dist/types/runtime/task.d.ts +12 -0
- package/dist/types/utils/registry.d.ts +15 -0
- package/package.json +1 -1
package/dist/owl.cjs.js
CHANGED
|
@@ -1596,6 +1596,14 @@ function remove(vnode, withBeforeRemove = false) {
|
|
|
1596
1596
|
vnode.remove();
|
|
1597
1597
|
}
|
|
1598
1598
|
|
|
1599
|
+
// Reactivity system
|
|
1600
|
+
var ComputationState;
|
|
1601
|
+
(function (ComputationState) {
|
|
1602
|
+
ComputationState[ComputationState["EXECUTED"] = 0] = "EXECUTED";
|
|
1603
|
+
ComputationState[ComputationState["STALE"] = 1] = "STALE";
|
|
1604
|
+
ComputationState[ComputationState["PENDING"] = 2] = "PENDING";
|
|
1605
|
+
})(ComputationState || (ComputationState = {}));
|
|
1606
|
+
|
|
1599
1607
|
// Maps fibers to thrown errors
|
|
1600
1608
|
const fibersInError = new WeakMap();
|
|
1601
1609
|
const nodeErrorHandlers = new WeakMap();
|
|
@@ -1658,6 +1666,233 @@ function handleError(params) {
|
|
|
1658
1666
|
}
|
|
1659
1667
|
}
|
|
1660
1668
|
|
|
1669
|
+
let Effects;
|
|
1670
|
+
let CurrentComputation;
|
|
1671
|
+
function signal(value, opts) {
|
|
1672
|
+
const atom = {
|
|
1673
|
+
value,
|
|
1674
|
+
observers: new Set(),
|
|
1675
|
+
name: opts === null || opts === void 0 ? void 0 : opts.name,
|
|
1676
|
+
};
|
|
1677
|
+
const read = () => {
|
|
1678
|
+
onReadAtom(atom);
|
|
1679
|
+
return atom.value;
|
|
1680
|
+
};
|
|
1681
|
+
const write = (newValue) => {
|
|
1682
|
+
if (typeof newValue === "function") {
|
|
1683
|
+
newValue = newValue(atom.value);
|
|
1684
|
+
}
|
|
1685
|
+
if (Object.is(atom.value, newValue))
|
|
1686
|
+
return;
|
|
1687
|
+
atom.value = newValue;
|
|
1688
|
+
onWriteAtom(atom);
|
|
1689
|
+
};
|
|
1690
|
+
return {
|
|
1691
|
+
get: read,
|
|
1692
|
+
set: write,
|
|
1693
|
+
};
|
|
1694
|
+
}
|
|
1695
|
+
function effect(fn, opts) {
|
|
1696
|
+
var _a, _b;
|
|
1697
|
+
const effectComputation = {
|
|
1698
|
+
state: ComputationState.STALE,
|
|
1699
|
+
value: undefined,
|
|
1700
|
+
compute() {
|
|
1701
|
+
// In case the cleanup read an atom.
|
|
1702
|
+
// todo: test it
|
|
1703
|
+
CurrentComputation = undefined;
|
|
1704
|
+
// `removeSources` is made by `runComputation`.
|
|
1705
|
+
unsubscribeEffect(effectComputation);
|
|
1706
|
+
CurrentComputation = effectComputation;
|
|
1707
|
+
return fn();
|
|
1708
|
+
},
|
|
1709
|
+
sources: new Set(),
|
|
1710
|
+
childrenEffect: [],
|
|
1711
|
+
name: opts === null || opts === void 0 ? void 0 : opts.name,
|
|
1712
|
+
};
|
|
1713
|
+
(_b = (_a = CurrentComputation === null || CurrentComputation === void 0 ? void 0 : CurrentComputation.childrenEffect) === null || _a === void 0 ? void 0 : _a.push) === null || _b === void 0 ? void 0 : _b.call(_a, effectComputation);
|
|
1714
|
+
updateComputation(effectComputation);
|
|
1715
|
+
// Remove sources and unsubscribe
|
|
1716
|
+
return () => {
|
|
1717
|
+
// In case the cleanup read an atom.
|
|
1718
|
+
// todo: test it
|
|
1719
|
+
const previousComputation = CurrentComputation;
|
|
1720
|
+
CurrentComputation = undefined;
|
|
1721
|
+
unsubscribeEffect(effectComputation);
|
|
1722
|
+
CurrentComputation = previousComputation;
|
|
1723
|
+
};
|
|
1724
|
+
}
|
|
1725
|
+
// export function computed<T>(fn: () => T, opts?: Opts) {
|
|
1726
|
+
// // todo: handle cleanup
|
|
1727
|
+
// let computedComputation: Computation = {
|
|
1728
|
+
// state: ComputationState.STALE,
|
|
1729
|
+
// sources: new Set(),
|
|
1730
|
+
// isEager: true,
|
|
1731
|
+
// compute: () => {
|
|
1732
|
+
// return fn();
|
|
1733
|
+
// },
|
|
1734
|
+
// value: undefined,
|
|
1735
|
+
// name: opts?.name,
|
|
1736
|
+
// };
|
|
1737
|
+
// updateComputation(computedComputation);
|
|
1738
|
+
// }
|
|
1739
|
+
function derived(fn, opts) {
|
|
1740
|
+
// todo: handle cleanup
|
|
1741
|
+
let derivedComputation;
|
|
1742
|
+
return () => {
|
|
1743
|
+
derivedComputation !== null && derivedComputation !== void 0 ? derivedComputation : (derivedComputation = {
|
|
1744
|
+
state: ComputationState.STALE,
|
|
1745
|
+
sources: new Set(),
|
|
1746
|
+
compute: () => {
|
|
1747
|
+
onWriteAtom(derivedComputation);
|
|
1748
|
+
return fn();
|
|
1749
|
+
},
|
|
1750
|
+
isDerived: true,
|
|
1751
|
+
value: undefined,
|
|
1752
|
+
observers: new Set(),
|
|
1753
|
+
name: opts === null || opts === void 0 ? void 0 : opts.name,
|
|
1754
|
+
});
|
|
1755
|
+
updateComputation(derivedComputation);
|
|
1756
|
+
return derivedComputation.value;
|
|
1757
|
+
};
|
|
1758
|
+
}
|
|
1759
|
+
function onReadAtom(atom) {
|
|
1760
|
+
if (!CurrentComputation)
|
|
1761
|
+
return;
|
|
1762
|
+
CurrentComputation.sources.add(atom);
|
|
1763
|
+
atom.observers.add(CurrentComputation);
|
|
1764
|
+
}
|
|
1765
|
+
function onWriteAtom(atom) {
|
|
1766
|
+
collectEffects(() => {
|
|
1767
|
+
for (const ctx of atom.observers) {
|
|
1768
|
+
if (ctx.state === ComputationState.EXECUTED) {
|
|
1769
|
+
if (ctx.isDerived)
|
|
1770
|
+
markDownstream(ctx);
|
|
1771
|
+
else
|
|
1772
|
+
Effects.push(ctx);
|
|
1773
|
+
}
|
|
1774
|
+
ctx.state = ComputationState.STALE;
|
|
1775
|
+
}
|
|
1776
|
+
});
|
|
1777
|
+
batchProcessEffects();
|
|
1778
|
+
}
|
|
1779
|
+
function collectEffects(fn) {
|
|
1780
|
+
if (Effects)
|
|
1781
|
+
return fn();
|
|
1782
|
+
Effects = [];
|
|
1783
|
+
try {
|
|
1784
|
+
return fn();
|
|
1785
|
+
}
|
|
1786
|
+
finally {
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
const batchProcessEffects = batched(processEffects);
|
|
1790
|
+
function processEffects() {
|
|
1791
|
+
if (!Effects)
|
|
1792
|
+
return;
|
|
1793
|
+
for (const computation of Effects) {
|
|
1794
|
+
updateComputation(computation);
|
|
1795
|
+
}
|
|
1796
|
+
Effects = undefined;
|
|
1797
|
+
}
|
|
1798
|
+
function withoutReactivity(fn) {
|
|
1799
|
+
return runWithComputation(undefined, fn);
|
|
1800
|
+
}
|
|
1801
|
+
function getCurrentComputation() {
|
|
1802
|
+
return CurrentComputation;
|
|
1803
|
+
}
|
|
1804
|
+
function setComputation(computation) {
|
|
1805
|
+
CurrentComputation = computation;
|
|
1806
|
+
}
|
|
1807
|
+
// todo: should probably use updateComputation instead.
|
|
1808
|
+
function runWithComputation(computation, fn) {
|
|
1809
|
+
const previousComputation = CurrentComputation;
|
|
1810
|
+
CurrentComputation = computation;
|
|
1811
|
+
let result;
|
|
1812
|
+
try {
|
|
1813
|
+
result = fn();
|
|
1814
|
+
}
|
|
1815
|
+
finally {
|
|
1816
|
+
CurrentComputation = previousComputation;
|
|
1817
|
+
}
|
|
1818
|
+
return result;
|
|
1819
|
+
}
|
|
1820
|
+
function updateComputation(computation) {
|
|
1821
|
+
var _a;
|
|
1822
|
+
const state = computation.state;
|
|
1823
|
+
if (computation.isDerived)
|
|
1824
|
+
onReadAtom(computation);
|
|
1825
|
+
if (state === ComputationState.EXECUTED)
|
|
1826
|
+
return;
|
|
1827
|
+
if (state === ComputationState.PENDING) {
|
|
1828
|
+
computeSources(computation);
|
|
1829
|
+
// If the state is still not stale after processing the sources, it means
|
|
1830
|
+
// none of the dependencies have changed.
|
|
1831
|
+
// todo: test it
|
|
1832
|
+
if (computation.state !== ComputationState.STALE) {
|
|
1833
|
+
computation.state = ComputationState.EXECUTED;
|
|
1834
|
+
return;
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
// todo: test performance. We might want to avoid removing the atoms to
|
|
1838
|
+
// directly re-add them at compute. Especially as we are making them stale.
|
|
1839
|
+
removeSources(computation);
|
|
1840
|
+
const previousComputation = CurrentComputation;
|
|
1841
|
+
CurrentComputation = computation;
|
|
1842
|
+
computation.value = (_a = computation.compute) === null || _a === void 0 ? void 0 : _a.call(computation);
|
|
1843
|
+
computation.state = ComputationState.EXECUTED;
|
|
1844
|
+
CurrentComputation = previousComputation;
|
|
1845
|
+
}
|
|
1846
|
+
function removeSources(computation) {
|
|
1847
|
+
const sources = computation.sources;
|
|
1848
|
+
for (const source of sources) {
|
|
1849
|
+
const observers = source.observers;
|
|
1850
|
+
observers.delete(computation);
|
|
1851
|
+
// todo: if source has no effect observer anymore, remove its sources too
|
|
1852
|
+
// todo: test it
|
|
1853
|
+
}
|
|
1854
|
+
sources.clear();
|
|
1855
|
+
}
|
|
1856
|
+
function unsubscribeEffect(effectComputation) {
|
|
1857
|
+
removeSources(effectComputation);
|
|
1858
|
+
cleanupEffect(effectComputation);
|
|
1859
|
+
for (const children of effectComputation.childrenEffect) {
|
|
1860
|
+
// Consider it executed to avoid it's re-execution
|
|
1861
|
+
// todo: make a test for it
|
|
1862
|
+
children.state = ComputationState.EXECUTED;
|
|
1863
|
+
removeSources(children);
|
|
1864
|
+
unsubscribeEffect(children);
|
|
1865
|
+
}
|
|
1866
|
+
effectComputation.childrenEffect.length = 0;
|
|
1867
|
+
}
|
|
1868
|
+
function cleanupEffect(computation) {
|
|
1869
|
+
// the computation.value of an effect is a cleanup function
|
|
1870
|
+
const cleanupFn = computation.value;
|
|
1871
|
+
if (cleanupFn && typeof cleanupFn === "function") {
|
|
1872
|
+
cleanupFn();
|
|
1873
|
+
computation.value = undefined;
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
function markDownstream(derived) {
|
|
1877
|
+
for (const observer of derived.observers) {
|
|
1878
|
+
// if the state has already been marked, skip it
|
|
1879
|
+
if (observer.state)
|
|
1880
|
+
continue;
|
|
1881
|
+
observer.state = ComputationState.PENDING;
|
|
1882
|
+
if (observer.isDerived)
|
|
1883
|
+
markDownstream(observer);
|
|
1884
|
+
else
|
|
1885
|
+
Effects.push(observer);
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
function computeSources(derived) {
|
|
1889
|
+
for (const source of derived.sources) {
|
|
1890
|
+
if (!("compute" in source))
|
|
1891
|
+
continue;
|
|
1892
|
+
updateComputation(source);
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1661
1896
|
function makeChildFiber(node, parent) {
|
|
1662
1897
|
let current = node.fiber;
|
|
1663
1898
|
if (current) {
|
|
@@ -1779,13 +2014,16 @@ class Fiber {
|
|
|
1779
2014
|
const node = this.node;
|
|
1780
2015
|
const root = this.root;
|
|
1781
2016
|
if (root) {
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
2017
|
+
// todo: should use updateComputation somewhere else.
|
|
2018
|
+
runWithComputation(node.signalComputation, () => {
|
|
2019
|
+
try {
|
|
2020
|
+
this.bdom = true;
|
|
2021
|
+
this.bdom = node.renderFn();
|
|
2022
|
+
}
|
|
2023
|
+
catch (e) {
|
|
2024
|
+
node.app.handleError({ node, error: e });
|
|
2025
|
+
}
|
|
2026
|
+
});
|
|
1789
2027
|
root.setCounter(root.counter - 1);
|
|
1790
2028
|
}
|
|
1791
2029
|
}
|
|
@@ -1917,11 +2155,6 @@ class MountFiber extends RootFiber {
|
|
|
1917
2155
|
|
|
1918
2156
|
// Special key to subscribe to, to be notified of key creation/deletion
|
|
1919
2157
|
const KEYCHANGES = Symbol("Key changes");
|
|
1920
|
-
// Used to specify the absence of a callback, can be used as WeakMap key but
|
|
1921
|
-
// should only be used as a sentinel value and never called.
|
|
1922
|
-
const NO_CALLBACK = () => {
|
|
1923
|
-
throw new Error("Called NO_CALLBACK. Owl is broken, please report this to the maintainers.");
|
|
1924
|
-
};
|
|
1925
2158
|
const objectToString = Object.prototype.toString;
|
|
1926
2159
|
const objectHasOwnProperty = Object.prototype.hasOwnProperty;
|
|
1927
2160
|
// Use arrays because Array.includes is faster than Set.has for small arrays
|
|
@@ -1958,8 +2191,8 @@ function canBeMadeReactive(value) {
|
|
|
1958
2191
|
* @param value the value make reactive
|
|
1959
2192
|
* @returns a reactive for the given object when possible, the original otherwise
|
|
1960
2193
|
*/
|
|
1961
|
-
function possiblyReactive(val
|
|
1962
|
-
return canBeMadeReactive(val) ? reactive(val
|
|
2194
|
+
function possiblyReactive(val) {
|
|
2195
|
+
return canBeMadeReactive(val) ? reactive(val) : val;
|
|
1963
2196
|
}
|
|
1964
2197
|
const skipped = new WeakSet();
|
|
1965
2198
|
/**
|
|
@@ -1981,7 +2214,23 @@ function markRaw(value) {
|
|
|
1981
2214
|
function toRaw(value) {
|
|
1982
2215
|
return targets.has(value) ? targets.get(value) : value;
|
|
1983
2216
|
}
|
|
1984
|
-
const
|
|
2217
|
+
const targetToKeysToAtomItem = new WeakMap();
|
|
2218
|
+
function getTargetKeyAtom(target, key) {
|
|
2219
|
+
let keyToAtomItem = targetToKeysToAtomItem.get(target);
|
|
2220
|
+
if (!keyToAtomItem) {
|
|
2221
|
+
keyToAtomItem = new Map();
|
|
2222
|
+
targetToKeysToAtomItem.set(target, keyToAtomItem);
|
|
2223
|
+
}
|
|
2224
|
+
let atom = keyToAtomItem.get(key);
|
|
2225
|
+
if (!atom) {
|
|
2226
|
+
atom = {
|
|
2227
|
+
value: undefined,
|
|
2228
|
+
observers: new Set(),
|
|
2229
|
+
};
|
|
2230
|
+
keyToAtomItem.set(key, atom);
|
|
2231
|
+
}
|
|
2232
|
+
return atom;
|
|
2233
|
+
}
|
|
1985
2234
|
/**
|
|
1986
2235
|
* Observes a given key on a target with an callback. The callback will be
|
|
1987
2236
|
* called when the given key changes on the target.
|
|
@@ -1991,22 +2240,8 @@ const targetToKeysToCallbacks = new WeakMap();
|
|
|
1991
2240
|
* or deletion)
|
|
1992
2241
|
* @param callback the function to call when the key changes
|
|
1993
2242
|
*/
|
|
1994
|
-
function
|
|
1995
|
-
|
|
1996
|
-
return;
|
|
1997
|
-
}
|
|
1998
|
-
if (!targetToKeysToCallbacks.get(target)) {
|
|
1999
|
-
targetToKeysToCallbacks.set(target, new Map());
|
|
2000
|
-
}
|
|
2001
|
-
const keyToCallbacks = targetToKeysToCallbacks.get(target);
|
|
2002
|
-
if (!keyToCallbacks.get(key)) {
|
|
2003
|
-
keyToCallbacks.set(key, new Set());
|
|
2004
|
-
}
|
|
2005
|
-
keyToCallbacks.get(key).add(callback);
|
|
2006
|
-
if (!callbacksToTargets.has(callback)) {
|
|
2007
|
-
callbacksToTargets.set(callback, new Set());
|
|
2008
|
-
}
|
|
2009
|
-
callbacksToTargets.get(callback).add(target);
|
|
2243
|
+
function onReadTargetKey(target, key) {
|
|
2244
|
+
onReadAtom(getTargetKeyAtom(target, key));
|
|
2010
2245
|
}
|
|
2011
2246
|
/**
|
|
2012
2247
|
* Notify Reactives that are observing a given target that a key has changed on
|
|
@@ -2017,60 +2252,16 @@ function observeTargetKey(target, key, callback) {
|
|
|
2017
2252
|
* @param key the key that changed (or Symbol `KEYCHANGES` if a key was created
|
|
2018
2253
|
* or deleted)
|
|
2019
2254
|
*/
|
|
2020
|
-
function
|
|
2021
|
-
const
|
|
2022
|
-
if (!
|
|
2255
|
+
function onWriteTargetKey(target, key) {
|
|
2256
|
+
const keyToAtomItem = targetToKeysToAtomItem.get(target);
|
|
2257
|
+
if (!keyToAtomItem) {
|
|
2023
2258
|
return;
|
|
2024
2259
|
}
|
|
2025
|
-
const
|
|
2026
|
-
if (!
|
|
2260
|
+
const atom = keyToAtomItem.get(key);
|
|
2261
|
+
if (!atom) {
|
|
2027
2262
|
return;
|
|
2028
2263
|
}
|
|
2029
|
-
|
|
2030
|
-
for (const callback of [...callbacks]) {
|
|
2031
|
-
clearReactivesForCallback(callback);
|
|
2032
|
-
callback();
|
|
2033
|
-
}
|
|
2034
|
-
}
|
|
2035
|
-
const callbacksToTargets = new WeakMap();
|
|
2036
|
-
/**
|
|
2037
|
-
* Clears all subscriptions of the Reactives associated with a given callback.
|
|
2038
|
-
*
|
|
2039
|
-
* @param callback the callback for which the reactives need to be cleared
|
|
2040
|
-
*/
|
|
2041
|
-
function clearReactivesForCallback(callback) {
|
|
2042
|
-
const targetsToClear = callbacksToTargets.get(callback);
|
|
2043
|
-
if (!targetsToClear) {
|
|
2044
|
-
return;
|
|
2045
|
-
}
|
|
2046
|
-
for (const target of targetsToClear) {
|
|
2047
|
-
const observedKeys = targetToKeysToCallbacks.get(target);
|
|
2048
|
-
if (!observedKeys) {
|
|
2049
|
-
continue;
|
|
2050
|
-
}
|
|
2051
|
-
for (const [key, callbacks] of observedKeys.entries()) {
|
|
2052
|
-
callbacks.delete(callback);
|
|
2053
|
-
if (!callbacks.size) {
|
|
2054
|
-
observedKeys.delete(key);
|
|
2055
|
-
}
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
|
-
targetsToClear.clear();
|
|
2059
|
-
}
|
|
2060
|
-
function getSubscriptions(callback) {
|
|
2061
|
-
const targets = callbacksToTargets.get(callback) || [];
|
|
2062
|
-
return [...targets].map((target) => {
|
|
2063
|
-
const keysToCallbacks = targetToKeysToCallbacks.get(target);
|
|
2064
|
-
let keys = [];
|
|
2065
|
-
if (keysToCallbacks) {
|
|
2066
|
-
for (const [key, cbs] of keysToCallbacks) {
|
|
2067
|
-
if (cbs.has(callback)) {
|
|
2068
|
-
keys.push(key);
|
|
2069
|
-
}
|
|
2070
|
-
}
|
|
2071
|
-
}
|
|
2072
|
-
return { target, keys };
|
|
2073
|
-
});
|
|
2264
|
+
onWriteAtom(atom);
|
|
2074
2265
|
}
|
|
2075
2266
|
// Maps reactive objects to the underlying target
|
|
2076
2267
|
const targets = new WeakMap();
|
|
@@ -2102,7 +2293,7 @@ const reactiveCache = new WeakMap();
|
|
|
2102
2293
|
* reactive has changed
|
|
2103
2294
|
* @returns a proxy that tracks changes to it
|
|
2104
2295
|
*/
|
|
2105
|
-
function reactive(target
|
|
2296
|
+
function reactive(target) {
|
|
2106
2297
|
if (!canBeMadeReactive(target)) {
|
|
2107
2298
|
throw new OwlError(`Cannot make the given value reactive`);
|
|
2108
2299
|
}
|
|
@@ -2111,22 +2302,19 @@ function reactive(target, callback = NO_CALLBACK) {
|
|
|
2111
2302
|
}
|
|
2112
2303
|
if (targets.has(target)) {
|
|
2113
2304
|
// target is reactive, create a reactive on the underlying object instead
|
|
2114
|
-
return
|
|
2115
|
-
}
|
|
2116
|
-
if (!reactiveCache.has(target)) {
|
|
2117
|
-
reactiveCache.set(target, new WeakMap());
|
|
2118
|
-
}
|
|
2119
|
-
const reactivesForTarget = reactiveCache.get(target);
|
|
2120
|
-
if (!reactivesForTarget.has(callback)) {
|
|
2121
|
-
const targetRawType = rawType(target);
|
|
2122
|
-
const handler = COLLECTION_RAW_TYPES.includes(targetRawType)
|
|
2123
|
-
? collectionsProxyHandler(target, callback, targetRawType)
|
|
2124
|
-
: basicProxyHandler(callback);
|
|
2125
|
-
const proxy = new Proxy(target, handler);
|
|
2126
|
-
reactivesForTarget.set(callback, proxy);
|
|
2127
|
-
targets.set(proxy, target);
|
|
2305
|
+
return target;
|
|
2128
2306
|
}
|
|
2129
|
-
|
|
2307
|
+
const reactive = reactiveCache.get(target);
|
|
2308
|
+
if (reactive)
|
|
2309
|
+
return reactive;
|
|
2310
|
+
const targetRawType = rawType(target);
|
|
2311
|
+
const handler = COLLECTION_RAW_TYPES.includes(targetRawType)
|
|
2312
|
+
? collectionsProxyHandler(target, targetRawType)
|
|
2313
|
+
: basicProxyHandler();
|
|
2314
|
+
const proxy = new Proxy(target, handler);
|
|
2315
|
+
reactiveCache.set(target, proxy);
|
|
2316
|
+
targets.set(proxy, target);
|
|
2317
|
+
return proxy;
|
|
2130
2318
|
}
|
|
2131
2319
|
/**
|
|
2132
2320
|
* Creates a basic proxy handler for regular objects and arrays.
|
|
@@ -2134,7 +2322,7 @@ function reactive(target, callback = NO_CALLBACK) {
|
|
|
2134
2322
|
* @param callback @see reactive
|
|
2135
2323
|
* @returns a proxy handler object
|
|
2136
2324
|
*/
|
|
2137
|
-
function basicProxyHandler(
|
|
2325
|
+
function basicProxyHandler() {
|
|
2138
2326
|
return {
|
|
2139
2327
|
get(target, key, receiver) {
|
|
2140
2328
|
// non-writable non-configurable properties cannot be made reactive
|
|
@@ -2142,41 +2330,41 @@ function basicProxyHandler(callback) {
|
|
|
2142
2330
|
if (desc && !desc.writable && !desc.configurable) {
|
|
2143
2331
|
return Reflect.get(target, key, receiver);
|
|
2144
2332
|
}
|
|
2145
|
-
|
|
2146
|
-
return possiblyReactive(Reflect.get(target, key, receiver)
|
|
2333
|
+
onReadTargetKey(target, key);
|
|
2334
|
+
return possiblyReactive(Reflect.get(target, key, receiver));
|
|
2147
2335
|
},
|
|
2148
2336
|
set(target, key, value, receiver) {
|
|
2149
2337
|
const hadKey = objectHasOwnProperty.call(target, key);
|
|
2150
2338
|
const originalValue = Reflect.get(target, key, receiver);
|
|
2151
2339
|
const ret = Reflect.set(target, key, toRaw(value), receiver);
|
|
2152
2340
|
if (!hadKey && objectHasOwnProperty.call(target, key)) {
|
|
2153
|
-
|
|
2341
|
+
onWriteTargetKey(target, KEYCHANGES);
|
|
2154
2342
|
}
|
|
2155
2343
|
// While Array length may trigger the set trap, it's not actually set by this
|
|
2156
2344
|
// method but is updated behind the scenes, and the trap is not called with the
|
|
2157
2345
|
// new value. We disable the "same-value-optimization" for it because of that.
|
|
2158
2346
|
if (originalValue !== Reflect.get(target, key, receiver) ||
|
|
2159
2347
|
(key === "length" && Array.isArray(target))) {
|
|
2160
|
-
|
|
2348
|
+
onWriteTargetKey(target, key);
|
|
2161
2349
|
}
|
|
2162
2350
|
return ret;
|
|
2163
2351
|
},
|
|
2164
2352
|
deleteProperty(target, key) {
|
|
2165
2353
|
const ret = Reflect.deleteProperty(target, key);
|
|
2166
2354
|
// TODO: only notify when something was actually deleted
|
|
2167
|
-
|
|
2168
|
-
|
|
2355
|
+
onWriteTargetKey(target, KEYCHANGES);
|
|
2356
|
+
onWriteTargetKey(target, key);
|
|
2169
2357
|
return ret;
|
|
2170
2358
|
},
|
|
2171
2359
|
ownKeys(target) {
|
|
2172
|
-
|
|
2360
|
+
onReadTargetKey(target, KEYCHANGES);
|
|
2173
2361
|
return Reflect.ownKeys(target);
|
|
2174
2362
|
},
|
|
2175
2363
|
has(target, key) {
|
|
2176
2364
|
// TODO: this observes all key changes instead of only the presence of the argument key
|
|
2177
2365
|
// observing the key itself would observe value changes instead of presence changes
|
|
2178
2366
|
// so we may need a finer grained system to distinguish observing value vs presence.
|
|
2179
|
-
|
|
2367
|
+
onReadTargetKey(target, KEYCHANGES);
|
|
2180
2368
|
return Reflect.has(target, key);
|
|
2181
2369
|
},
|
|
2182
2370
|
};
|
|
@@ -2189,11 +2377,11 @@ function basicProxyHandler(callback) {
|
|
|
2189
2377
|
* @param target @see reactive
|
|
2190
2378
|
* @param callback @see reactive
|
|
2191
2379
|
*/
|
|
2192
|
-
function makeKeyObserver(methodName, target
|
|
2380
|
+
function makeKeyObserver(methodName, target) {
|
|
2193
2381
|
return (key) => {
|
|
2194
2382
|
key = toRaw(key);
|
|
2195
|
-
|
|
2196
|
-
return possiblyReactive(target[methodName](key)
|
|
2383
|
+
onReadTargetKey(target, key);
|
|
2384
|
+
return possiblyReactive(target[methodName](key));
|
|
2197
2385
|
};
|
|
2198
2386
|
}
|
|
2199
2387
|
/**
|
|
@@ -2204,14 +2392,14 @@ function makeKeyObserver(methodName, target, callback) {
|
|
|
2204
2392
|
* @param target @see reactive
|
|
2205
2393
|
* @param callback @see reactive
|
|
2206
2394
|
*/
|
|
2207
|
-
function makeIteratorObserver(methodName, target
|
|
2395
|
+
function makeIteratorObserver(methodName, target) {
|
|
2208
2396
|
return function* () {
|
|
2209
|
-
|
|
2397
|
+
onReadTargetKey(target, KEYCHANGES);
|
|
2210
2398
|
const keys = target.keys();
|
|
2211
2399
|
for (const item of target[methodName]()) {
|
|
2212
2400
|
const key = keys.next().value;
|
|
2213
|
-
|
|
2214
|
-
yield possiblyReactive(item
|
|
2401
|
+
onReadTargetKey(target, key);
|
|
2402
|
+
yield possiblyReactive(item);
|
|
2215
2403
|
}
|
|
2216
2404
|
};
|
|
2217
2405
|
}
|
|
@@ -2223,12 +2411,12 @@ function makeIteratorObserver(methodName, target, callback) {
|
|
|
2223
2411
|
* @param target @see reactive
|
|
2224
2412
|
* @param callback @see reactive
|
|
2225
2413
|
*/
|
|
2226
|
-
function makeForEachObserver(target
|
|
2414
|
+
function makeForEachObserver(target) {
|
|
2227
2415
|
return function forEach(forEachCb, thisArg) {
|
|
2228
|
-
|
|
2416
|
+
onReadTargetKey(target, KEYCHANGES);
|
|
2229
2417
|
target.forEach(function (val, key, targetObj) {
|
|
2230
|
-
|
|
2231
|
-
forEachCb.call(thisArg, possiblyReactive(val
|
|
2418
|
+
onReadTargetKey(target, key);
|
|
2419
|
+
forEachCb.call(thisArg, possiblyReactive(val), possiblyReactive(key), possiblyReactive(targetObj));
|
|
2232
2420
|
}, thisArg);
|
|
2233
2421
|
};
|
|
2234
2422
|
}
|
|
@@ -2250,10 +2438,10 @@ function delegateAndNotify(setterName, getterName, target) {
|
|
|
2250
2438
|
const ret = target[setterName](key, value);
|
|
2251
2439
|
const hasKey = target.has(key);
|
|
2252
2440
|
if (hadKey !== hasKey) {
|
|
2253
|
-
|
|
2441
|
+
onWriteTargetKey(target, KEYCHANGES);
|
|
2254
2442
|
}
|
|
2255
2443
|
if (originalValue !== target[getterName](key)) {
|
|
2256
|
-
|
|
2444
|
+
onWriteTargetKey(target, key);
|
|
2257
2445
|
}
|
|
2258
2446
|
return ret;
|
|
2259
2447
|
};
|
|
@@ -2268,9 +2456,9 @@ function makeClearNotifier(target) {
|
|
|
2268
2456
|
return () => {
|
|
2269
2457
|
const allKeys = [...target.keys()];
|
|
2270
2458
|
target.clear();
|
|
2271
|
-
|
|
2459
|
+
onWriteTargetKey(target, KEYCHANGES);
|
|
2272
2460
|
for (const key of allKeys) {
|
|
2273
|
-
|
|
2461
|
+
onWriteTargetKey(target, key);
|
|
2274
2462
|
}
|
|
2275
2463
|
};
|
|
2276
2464
|
}
|
|
@@ -2282,40 +2470,40 @@ function makeClearNotifier(target) {
|
|
|
2282
2470
|
* reactives that the key which is being added or deleted has been modified.
|
|
2283
2471
|
*/
|
|
2284
2472
|
const rawTypeToFuncHandlers = {
|
|
2285
|
-
Set: (target
|
|
2286
|
-
has: makeKeyObserver("has", target
|
|
2473
|
+
Set: (target) => ({
|
|
2474
|
+
has: makeKeyObserver("has", target),
|
|
2287
2475
|
add: delegateAndNotify("add", "has", target),
|
|
2288
2476
|
delete: delegateAndNotify("delete", "has", target),
|
|
2289
|
-
keys: makeIteratorObserver("keys", target
|
|
2290
|
-
values: makeIteratorObserver("values", target
|
|
2291
|
-
entries: makeIteratorObserver("entries", target
|
|
2292
|
-
[Symbol.iterator]: makeIteratorObserver(Symbol.iterator, target
|
|
2293
|
-
forEach: makeForEachObserver(target
|
|
2477
|
+
keys: makeIteratorObserver("keys", target),
|
|
2478
|
+
values: makeIteratorObserver("values", target),
|
|
2479
|
+
entries: makeIteratorObserver("entries", target),
|
|
2480
|
+
[Symbol.iterator]: makeIteratorObserver(Symbol.iterator, target),
|
|
2481
|
+
forEach: makeForEachObserver(target),
|
|
2294
2482
|
clear: makeClearNotifier(target),
|
|
2295
2483
|
get size() {
|
|
2296
|
-
|
|
2484
|
+
onReadTargetKey(target, KEYCHANGES);
|
|
2297
2485
|
return target.size;
|
|
2298
2486
|
},
|
|
2299
2487
|
}),
|
|
2300
|
-
Map: (target
|
|
2301
|
-
has: makeKeyObserver("has", target
|
|
2302
|
-
get: makeKeyObserver("get", target
|
|
2488
|
+
Map: (target) => ({
|
|
2489
|
+
has: makeKeyObserver("has", target),
|
|
2490
|
+
get: makeKeyObserver("get", target),
|
|
2303
2491
|
set: delegateAndNotify("set", "get", target),
|
|
2304
2492
|
delete: delegateAndNotify("delete", "has", target),
|
|
2305
|
-
keys: makeIteratorObserver("keys", target
|
|
2306
|
-
values: makeIteratorObserver("values", target
|
|
2307
|
-
entries: makeIteratorObserver("entries", target
|
|
2308
|
-
[Symbol.iterator]: makeIteratorObserver(Symbol.iterator, target
|
|
2309
|
-
forEach: makeForEachObserver(target
|
|
2493
|
+
keys: makeIteratorObserver("keys", target),
|
|
2494
|
+
values: makeIteratorObserver("values", target),
|
|
2495
|
+
entries: makeIteratorObserver("entries", target),
|
|
2496
|
+
[Symbol.iterator]: makeIteratorObserver(Symbol.iterator, target),
|
|
2497
|
+
forEach: makeForEachObserver(target),
|
|
2310
2498
|
clear: makeClearNotifier(target),
|
|
2311
2499
|
get size() {
|
|
2312
|
-
|
|
2500
|
+
onReadTargetKey(target, KEYCHANGES);
|
|
2313
2501
|
return target.size;
|
|
2314
2502
|
},
|
|
2315
2503
|
}),
|
|
2316
|
-
WeakMap: (target
|
|
2317
|
-
has: makeKeyObserver("has", target
|
|
2318
|
-
get: makeKeyObserver("get", target
|
|
2504
|
+
WeakMap: (target) => ({
|
|
2505
|
+
has: makeKeyObserver("has", target),
|
|
2506
|
+
get: makeKeyObserver("get", target),
|
|
2319
2507
|
set: delegateAndNotify("set", "get", target),
|
|
2320
2508
|
delete: delegateAndNotify("delete", "has", target),
|
|
2321
2509
|
}),
|
|
@@ -2327,18 +2515,18 @@ const rawTypeToFuncHandlers = {
|
|
|
2327
2515
|
* @param target @see reactive
|
|
2328
2516
|
* @returns a proxy handler object
|
|
2329
2517
|
*/
|
|
2330
|
-
function collectionsProxyHandler(target,
|
|
2518
|
+
function collectionsProxyHandler(target, targetRawType) {
|
|
2331
2519
|
// TODO: if performance is an issue we can create the special handlers lazily when each
|
|
2332
2520
|
// property is read.
|
|
2333
|
-
const specialHandlers = rawTypeToFuncHandlers[targetRawType](target
|
|
2334
|
-
return Object.assign(basicProxyHandler(
|
|
2521
|
+
const specialHandlers = rawTypeToFuncHandlers[targetRawType](target);
|
|
2522
|
+
return Object.assign(basicProxyHandler(), {
|
|
2335
2523
|
// FIXME: probably broken when part of prototype chain since we ignore the receiver
|
|
2336
2524
|
get(target, key) {
|
|
2337
2525
|
if (objectHasOwnProperty.call(specialHandlers, key)) {
|
|
2338
2526
|
return specialHandlers[key];
|
|
2339
2527
|
}
|
|
2340
|
-
|
|
2341
|
-
return possiblyReactive(target[key]
|
|
2528
|
+
onReadTargetKey(target, key);
|
|
2529
|
+
return possiblyReactive(target[key]);
|
|
2342
2530
|
},
|
|
2343
2531
|
});
|
|
2344
2532
|
}
|
|
@@ -2372,7 +2560,6 @@ function applyDefaultProps(props, defaultProps) {
|
|
|
2372
2560
|
// -----------------------------------------------------------------------------
|
|
2373
2561
|
// Integration with reactivity system (useState)
|
|
2374
2562
|
// -----------------------------------------------------------------------------
|
|
2375
|
-
const batchedRenderFunctions = new WeakMap();
|
|
2376
2563
|
/**
|
|
2377
2564
|
* Creates a reactive object that will be observed by the current component.
|
|
2378
2565
|
* Reading data from the returned object (eg during rendering) will cause the
|
|
@@ -2384,15 +2571,7 @@ const batchedRenderFunctions = new WeakMap();
|
|
|
2384
2571
|
* @see reactive
|
|
2385
2572
|
*/
|
|
2386
2573
|
function useState(state) {
|
|
2387
|
-
|
|
2388
|
-
let render = batchedRenderFunctions.get(node);
|
|
2389
|
-
if (!render) {
|
|
2390
|
-
render = batched(node.render.bind(node, false));
|
|
2391
|
-
batchedRenderFunctions.set(node, render);
|
|
2392
|
-
// manual implementation of onWillDestroy to break cyclic dependency
|
|
2393
|
-
node.willDestroy.push(clearReactivesForCallback.bind(null, render));
|
|
2394
|
-
}
|
|
2395
|
-
return reactive(state, render);
|
|
2574
|
+
return reactive(state);
|
|
2396
2575
|
}
|
|
2397
2576
|
class ComponentNode {
|
|
2398
2577
|
constructor(C, props, app, parent, parentKey) {
|
|
@@ -2415,6 +2594,13 @@ class ComponentNode {
|
|
|
2415
2594
|
this.parent = parent;
|
|
2416
2595
|
this.props = props;
|
|
2417
2596
|
this.parentKey = parentKey;
|
|
2597
|
+
this.pluginManager = parent ? parent.pluginManager : app.pluginManager;
|
|
2598
|
+
this.signalComputation = {
|
|
2599
|
+
value: undefined,
|
|
2600
|
+
compute: () => this.render(false),
|
|
2601
|
+
sources: new Set(),
|
|
2602
|
+
state: ComputationState.EXECUTED,
|
|
2603
|
+
};
|
|
2418
2604
|
const defaultProps = C.defaultProps;
|
|
2419
2605
|
props = Object.assign({}, props);
|
|
2420
2606
|
if (defaultProps) {
|
|
@@ -2422,16 +2608,13 @@ class ComponentNode {
|
|
|
2422
2608
|
}
|
|
2423
2609
|
const env = (parent && parent.childEnv) || app.env;
|
|
2424
2610
|
this.childEnv = env;
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
if (prop && typeof prop === "object" && targets.has(prop)) {
|
|
2428
|
-
props[key] = useState(prop);
|
|
2429
|
-
}
|
|
2430
|
-
}
|
|
2611
|
+
const previousComputation = getCurrentComputation();
|
|
2612
|
+
setComputation(this.signalComputation);
|
|
2431
2613
|
this.component = new C(props, env, this);
|
|
2432
2614
|
const ctx = Object.assign(Object.create(this.component), { this: this.component });
|
|
2433
2615
|
this.renderFn = app.getTemplate(C.template).bind(this.component, ctx, this);
|
|
2434
2616
|
this.component.setup();
|
|
2617
|
+
setComputation(previousComputation);
|
|
2435
2618
|
currentNode = null;
|
|
2436
2619
|
}
|
|
2437
2620
|
mountComponent(target, options) {
|
|
@@ -2446,7 +2629,11 @@ class ComponentNode {
|
|
|
2446
2629
|
}
|
|
2447
2630
|
const component = this.component;
|
|
2448
2631
|
try {
|
|
2449
|
-
|
|
2632
|
+
let prom;
|
|
2633
|
+
withoutReactivity(() => {
|
|
2634
|
+
prom = Promise.all(this.willStart.map((f) => f.call(component)));
|
|
2635
|
+
});
|
|
2636
|
+
await prom;
|
|
2450
2637
|
}
|
|
2451
2638
|
catch (e) {
|
|
2452
2639
|
this.app.handleError({ node: this, error: e });
|
|
@@ -2555,15 +2742,10 @@ class ComponentNode {
|
|
|
2555
2742
|
if (defaultProps) {
|
|
2556
2743
|
applyDefaultProps(props, defaultProps);
|
|
2557
2744
|
}
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
props[key] = useState(prop);
|
|
2563
|
-
}
|
|
2564
|
-
}
|
|
2565
|
-
currentNode = null;
|
|
2566
|
-
const prom = Promise.all(this.willUpdateProps.map((f) => f.call(component, props)));
|
|
2745
|
+
let prom;
|
|
2746
|
+
withoutReactivity(() => {
|
|
2747
|
+
prom = Promise.all(this.willUpdateProps.map((f) => f.call(component, props)));
|
|
2748
|
+
});
|
|
2567
2749
|
await prom;
|
|
2568
2750
|
if (fiber !== this.fiber) {
|
|
2569
2751
|
return;
|
|
@@ -2671,10 +2853,6 @@ class ComponentNode {
|
|
|
2671
2853
|
get name() {
|
|
2672
2854
|
return this.component.constructor.name;
|
|
2673
2855
|
}
|
|
2674
|
-
get subscriptions() {
|
|
2675
|
-
const render = batchedRenderFunctions.get(this);
|
|
2676
|
-
return render ? getSubscriptions(render) : [];
|
|
2677
|
-
}
|
|
2678
2856
|
}
|
|
2679
2857
|
|
|
2680
2858
|
const TIMEOUT = Symbol("timeout");
|
|
@@ -2796,6 +2974,9 @@ class Component {
|
|
|
2796
2974
|
this.env = env;
|
|
2797
2975
|
this.__owl__ = node;
|
|
2798
2976
|
}
|
|
2977
|
+
get plugins() {
|
|
2978
|
+
return this.__owl__.pluginManager.plugins;
|
|
2979
|
+
}
|
|
2799
2980
|
setup() { }
|
|
2800
2981
|
render(deep = false) {
|
|
2801
2982
|
this.__owl__.render(deep === true);
|
|
@@ -5911,6 +6092,171 @@ class Scheduler {
|
|
|
5911
6092
|
// interactions with other code, such as test frameworks that override them
|
|
5912
6093
|
Scheduler.requestAnimationFrame = window.requestAnimationFrame.bind(window);
|
|
5913
6094
|
|
|
6095
|
+
// import { PluginCtor } from "./component";
|
|
6096
|
+
class Plugin {
|
|
6097
|
+
constructor() {
|
|
6098
|
+
this.plugins = {};
|
|
6099
|
+
this.resources = {};
|
|
6100
|
+
this.__meta__ = { isDestroyed: false };
|
|
6101
|
+
// getResource(name: string) {
|
|
6102
|
+
// // todo
|
|
6103
|
+
// }
|
|
6104
|
+
// dispatchTo(resourceName, ...args) {
|
|
6105
|
+
// for (let handler of this.getResource(name)) {
|
|
6106
|
+
// if (typeof handler === "function") {
|
|
6107
|
+
// handler(...args);
|
|
6108
|
+
// } else {
|
|
6109
|
+
// throw new Error("resource value should be a function")
|
|
6110
|
+
// }
|
|
6111
|
+
// }
|
|
6112
|
+
// }
|
|
6113
|
+
}
|
|
6114
|
+
setup() { }
|
|
6115
|
+
destroy() { }
|
|
6116
|
+
get isDestroyed() {
|
|
6117
|
+
return this.__meta__.isDestroyed;
|
|
6118
|
+
}
|
|
6119
|
+
}
|
|
6120
|
+
Plugin.id = "";
|
|
6121
|
+
Plugin.dependencies = [];
|
|
6122
|
+
// can act and replace another plugin
|
|
6123
|
+
// static replaceOtherPlugin: null | string = null;
|
|
6124
|
+
// can define the type of resources, and some information, such as, is the
|
|
6125
|
+
// resource global or not
|
|
6126
|
+
Plugin.resources = {};
|
|
6127
|
+
class PluginManager {
|
|
6128
|
+
constructor(parent, Plugins) {
|
|
6129
|
+
this._children = [];
|
|
6130
|
+
this._parent = parent;
|
|
6131
|
+
parent === null || parent === void 0 ? void 0 : parent._children.push(this);
|
|
6132
|
+
this.plugins = parent ? Object.create(parent.plugins) : {};
|
|
6133
|
+
this.resources = parent ? Object.create(parent.resources) : {};
|
|
6134
|
+
// instantiate all plugins
|
|
6135
|
+
const plugins = [];
|
|
6136
|
+
const PLUGINS = Array.isArray(Plugins) ? Plugins : Plugins();
|
|
6137
|
+
for (let P of toposort(PLUGINS, this.plugins)) {
|
|
6138
|
+
if (P.resources) {
|
|
6139
|
+
for (let r in P.resources) {
|
|
6140
|
+
const sources = reactive({});
|
|
6141
|
+
const fn = derived(() => {
|
|
6142
|
+
const result = [];
|
|
6143
|
+
for (let name in sources) {
|
|
6144
|
+
const plugin = sources[name];
|
|
6145
|
+
const value = plugin.resources[r];
|
|
6146
|
+
if (Array.isArray(value)) {
|
|
6147
|
+
result.push(...value);
|
|
6148
|
+
}
|
|
6149
|
+
else {
|
|
6150
|
+
result.push(value);
|
|
6151
|
+
}
|
|
6152
|
+
}
|
|
6153
|
+
return result;
|
|
6154
|
+
});
|
|
6155
|
+
this.resources[r] = { sources, fn };
|
|
6156
|
+
}
|
|
6157
|
+
}
|
|
6158
|
+
const p = new P();
|
|
6159
|
+
plugins.push(p);
|
|
6160
|
+
this.plugins[P.id] = p;
|
|
6161
|
+
for (let dep of P.dependencies) {
|
|
6162
|
+
p.plugins[dep] = this.plugins[dep];
|
|
6163
|
+
}
|
|
6164
|
+
}
|
|
6165
|
+
// aggregate resources
|
|
6166
|
+
for (let name in this.plugins) {
|
|
6167
|
+
const p = this.plugins[name];
|
|
6168
|
+
for (let r in p.resources) {
|
|
6169
|
+
this.resources[r].sources[name] = p;
|
|
6170
|
+
// const value = p.resources[r];
|
|
6171
|
+
// if (Array.isArray(value)) {
|
|
6172
|
+
// this.resources[r].push(...value);
|
|
6173
|
+
// } else {
|
|
6174
|
+
// this.resources[r].push(value);
|
|
6175
|
+
// }
|
|
6176
|
+
}
|
|
6177
|
+
}
|
|
6178
|
+
// setup phase
|
|
6179
|
+
for (let p of plugins) {
|
|
6180
|
+
p.setup();
|
|
6181
|
+
}
|
|
6182
|
+
}
|
|
6183
|
+
destroy() {
|
|
6184
|
+
for (let children of this._children) {
|
|
6185
|
+
children.destroy();
|
|
6186
|
+
}
|
|
6187
|
+
const plugins = [];
|
|
6188
|
+
for (let id in this.plugins) {
|
|
6189
|
+
if (this.plugins.hasOwnProperty(id)) {
|
|
6190
|
+
const plugin = this.plugins[id];
|
|
6191
|
+
// resources
|
|
6192
|
+
for (let r in plugin.resources) {
|
|
6193
|
+
delete this.resources[r].sources[id];
|
|
6194
|
+
}
|
|
6195
|
+
plugins.push(this.plugins[id]);
|
|
6196
|
+
delete this.plugins[id];
|
|
6197
|
+
}
|
|
6198
|
+
}
|
|
6199
|
+
while (plugins.length) {
|
|
6200
|
+
const plugin = plugins.pop();
|
|
6201
|
+
plugin.destroy();
|
|
6202
|
+
plugin.__meta__.isDestroyed = true;
|
|
6203
|
+
}
|
|
6204
|
+
}
|
|
6205
|
+
getPlugin(name) {
|
|
6206
|
+
return this.plugins[name] || null;
|
|
6207
|
+
}
|
|
6208
|
+
getResource(name) {
|
|
6209
|
+
return this.resources[name].fn();
|
|
6210
|
+
}
|
|
6211
|
+
}
|
|
6212
|
+
function toposort(Plugins, plugins) {
|
|
6213
|
+
const visited = new Set();
|
|
6214
|
+
const temp = new Set();
|
|
6215
|
+
const sorted = [];
|
|
6216
|
+
const mapping = {};
|
|
6217
|
+
for (const P of Plugins) {
|
|
6218
|
+
if (!P.id.length) {
|
|
6219
|
+
throw new Error(`Plugin ${P.name} has no id`);
|
|
6220
|
+
}
|
|
6221
|
+
if (P.id in mapping) {
|
|
6222
|
+
throw new Error("A plugin with the same ID is already defined");
|
|
6223
|
+
}
|
|
6224
|
+
mapping[P.id] = P;
|
|
6225
|
+
}
|
|
6226
|
+
const visit = (P) => {
|
|
6227
|
+
if (visited.has(P.id))
|
|
6228
|
+
return;
|
|
6229
|
+
if (temp.has(P.id)) {
|
|
6230
|
+
throw new Error(`Circular dependency: ${P.id}`);
|
|
6231
|
+
}
|
|
6232
|
+
temp.add(P.id);
|
|
6233
|
+
for (const dep of P.dependencies || []) {
|
|
6234
|
+
const Dep = mapping[dep];
|
|
6235
|
+
if (Dep) {
|
|
6236
|
+
visit(Dep);
|
|
6237
|
+
}
|
|
6238
|
+
else {
|
|
6239
|
+
if (!(dep in plugins)) {
|
|
6240
|
+
throw new Error(`Missing dependency "${dep}" for plugin "${P.id}"`);
|
|
6241
|
+
}
|
|
6242
|
+
}
|
|
6243
|
+
}
|
|
6244
|
+
temp.delete(P.id);
|
|
6245
|
+
visited.add(P.id);
|
|
6246
|
+
sorted.push(P);
|
|
6247
|
+
};
|
|
6248
|
+
for (const P of Plugins) {
|
|
6249
|
+
visit(P);
|
|
6250
|
+
}
|
|
6251
|
+
return sorted;
|
|
6252
|
+
}
|
|
6253
|
+
function usePlugins(Plugins) {
|
|
6254
|
+
const node = getCurrent();
|
|
6255
|
+
const manager = new PluginManager(node.pluginManager, Plugins);
|
|
6256
|
+
node.pluginManager = manager;
|
|
6257
|
+
onWillDestroy(() => manager.destroy());
|
|
6258
|
+
}
|
|
6259
|
+
|
|
5914
6260
|
let hasBeenLogged = false;
|
|
5915
6261
|
const apps = new Set();
|
|
5916
6262
|
window.__OWL_DEVTOOLS__ || (window.__OWL_DEVTOOLS__ = { apps, Fiber, RootFiber, toRaw, reactive });
|
|
@@ -5923,6 +6269,7 @@ class App extends TemplateSet {
|
|
|
5923
6269
|
this.name = config.name || "";
|
|
5924
6270
|
this.Root = Root;
|
|
5925
6271
|
apps.add(this);
|
|
6272
|
+
this.pluginManager = new PluginManager(null, config.Plugins || []);
|
|
5926
6273
|
if (config.test) {
|
|
5927
6274
|
this.dev = true;
|
|
5928
6275
|
}
|
|
@@ -6138,6 +6485,43 @@ const mainEventHandler = (data, ev, currentTarget) => {
|
|
|
6138
6485
|
return stopped;
|
|
6139
6486
|
};
|
|
6140
6487
|
|
|
6488
|
+
class Registry {
|
|
6489
|
+
constructor(name, schema) {
|
|
6490
|
+
this._map = reactive(Object.create(null));
|
|
6491
|
+
this._name = name || "registry";
|
|
6492
|
+
this._schema = schema;
|
|
6493
|
+
const entries = derived(() => {
|
|
6494
|
+
return Object.entries(this._map)
|
|
6495
|
+
.sort((el1, el2) => el1[1][0] - el2[1][0])
|
|
6496
|
+
.map(([str, elem]) => [str, elem[1]]);
|
|
6497
|
+
});
|
|
6498
|
+
const items = derived(() => entries().map((e) => e[1]));
|
|
6499
|
+
Object.defineProperty(this, "items", {
|
|
6500
|
+
get() {
|
|
6501
|
+
return items;
|
|
6502
|
+
},
|
|
6503
|
+
});
|
|
6504
|
+
Object.defineProperty(this, "entries", {
|
|
6505
|
+
get() {
|
|
6506
|
+
return entries;
|
|
6507
|
+
},
|
|
6508
|
+
});
|
|
6509
|
+
}
|
|
6510
|
+
set(key, value, sequence = 50) {
|
|
6511
|
+
if (this._schema) {
|
|
6512
|
+
validate(value, this._schema);
|
|
6513
|
+
}
|
|
6514
|
+
this._map[key] = [sequence, value];
|
|
6515
|
+
}
|
|
6516
|
+
get(key, defaultValue) {
|
|
6517
|
+
const hasKey = key in this._map;
|
|
6518
|
+
if (!hasKey && arguments.length < 2) {
|
|
6519
|
+
throw new Error(`KeyNotFoundError: Cannot find key "${key}" in this registry`);
|
|
6520
|
+
}
|
|
6521
|
+
return hasKey ? this._map[key][1] : defaultValue;
|
|
6522
|
+
}
|
|
6523
|
+
}
|
|
6524
|
+
|
|
6141
6525
|
function status(component) {
|
|
6142
6526
|
switch (component.__owl__.status) {
|
|
6143
6527
|
case 0 /* NEW */:
|
|
@@ -6211,21 +6595,26 @@ function useChildSubEnv(envExtension) {
|
|
|
6211
6595
|
* NaN !== NaN, which will cause the effect to rerun on every patch.
|
|
6212
6596
|
*/
|
|
6213
6597
|
function useEffect(effect, computeDependencies = () => [NaN]) {
|
|
6598
|
+
const context = getCurrent().component.__owl__.signalComputation;
|
|
6214
6599
|
let cleanup;
|
|
6215
6600
|
let dependencies;
|
|
6216
|
-
|
|
6217
|
-
dependencies = computeDependencies();
|
|
6601
|
+
const runEffect = () => runWithComputation(context, () => {
|
|
6218
6602
|
cleanup = effect(...dependencies);
|
|
6219
6603
|
});
|
|
6604
|
+
const computeDependenciesWithContext = () => runWithComputation(context, computeDependencies);
|
|
6605
|
+
onMounted(() => {
|
|
6606
|
+
dependencies = computeDependenciesWithContext();
|
|
6607
|
+
runEffect();
|
|
6608
|
+
});
|
|
6220
6609
|
onPatched(() => {
|
|
6221
|
-
const newDeps =
|
|
6610
|
+
const newDeps = computeDependenciesWithContext();
|
|
6222
6611
|
const shouldReapply = newDeps.some((val, i) => val !== dependencies[i]);
|
|
6223
6612
|
if (shouldReapply) {
|
|
6224
6613
|
dependencies = newDeps;
|
|
6225
6614
|
if (cleanup) {
|
|
6226
6615
|
cleanup();
|
|
6227
6616
|
}
|
|
6228
|
-
|
|
6617
|
+
runEffect();
|
|
6229
6618
|
}
|
|
6230
6619
|
});
|
|
6231
6620
|
onWillUnmount(() => cleanup && cleanup());
|
|
@@ -6289,9 +6678,14 @@ exports.App = App;
|
|
|
6289
6678
|
exports.Component = Component;
|
|
6290
6679
|
exports.EventBus = EventBus;
|
|
6291
6680
|
exports.OwlError = OwlError;
|
|
6681
|
+
exports.Plugin = Plugin;
|
|
6682
|
+
exports.PluginManager = PluginManager;
|
|
6683
|
+
exports.Registry = Registry;
|
|
6292
6684
|
exports.__info__ = __info__;
|
|
6293
6685
|
exports.batched = batched;
|
|
6294
6686
|
exports.blockDom = blockDom;
|
|
6687
|
+
exports.derived = derived;
|
|
6688
|
+
exports.effect = effect;
|
|
6295
6689
|
exports.htmlEscape = htmlEscape;
|
|
6296
6690
|
exports.loadFile = loadFile;
|
|
6297
6691
|
exports.markRaw = markRaw;
|
|
@@ -6308,6 +6702,7 @@ exports.onWillStart = onWillStart;
|
|
|
6308
6702
|
exports.onWillUnmount = onWillUnmount;
|
|
6309
6703
|
exports.onWillUpdateProps = onWillUpdateProps;
|
|
6310
6704
|
exports.reactive = reactive;
|
|
6705
|
+
exports.signal = signal;
|
|
6311
6706
|
exports.status = status;
|
|
6312
6707
|
exports.toRaw = toRaw;
|
|
6313
6708
|
exports.useChildSubEnv = useChildSubEnv;
|
|
@@ -6315,15 +6710,17 @@ exports.useComponent = useComponent;
|
|
|
6315
6710
|
exports.useEffect = useEffect;
|
|
6316
6711
|
exports.useEnv = useEnv;
|
|
6317
6712
|
exports.useExternalListener = useExternalListener;
|
|
6713
|
+
exports.usePlugins = usePlugins;
|
|
6318
6714
|
exports.useRef = useRef;
|
|
6319
6715
|
exports.useState = useState;
|
|
6320
6716
|
exports.useSubEnv = useSubEnv;
|
|
6321
6717
|
exports.validate = validate;
|
|
6322
6718
|
exports.validateType = validateType;
|
|
6323
6719
|
exports.whenReady = whenReady;
|
|
6720
|
+
exports.withoutReactivity = withoutReactivity;
|
|
6324
6721
|
exports.xml = xml;
|
|
6325
6722
|
|
|
6326
6723
|
|
|
6327
|
-
__info__.date = '2025-
|
|
6328
|
-
__info__.hash = '
|
|
6724
|
+
__info__.date = '2025-11-21T12:26:21.756Z';
|
|
6725
|
+
__info__.hash = '938f3f6';
|
|
6329
6726
|
__info__.url = 'https://github.com/odoo/owl';
|