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