@oscarpalmer/mora 0.33.0 → 0.35.0
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/constants.d.mts +2 -2
- package/dist/helpers/proxy.d.mts +8 -8
- package/dist/helpers/proxy.mjs +32 -25
- package/dist/helpers/subscription.d.mts +3 -3
- package/dist/helpers/value.d.mts +9 -8
- package/dist/helpers/value.mjs +15 -11
- package/dist/index.d.mts +2 -2
- package/dist/models.d.mts +40 -37
- package/dist/mora.full.mjs +195 -167
- package/dist/value/array.mjs +53 -41
- package/dist/value/computed.d.mts +2 -2
- package/dist/value/computed.mjs +3 -5
- package/dist/value/readonly.d.mts +2 -2
- package/dist/value/readonly.mjs +16 -19
- package/dist/value/signal.mjs +13 -13
- package/dist/value/store.mjs +4 -6
- package/package.json +2 -2
- package/src/batch.ts +2 -2
- package/src/constants.ts +7 -2
- package/src/helpers/is.ts +1 -3
- package/src/helpers/proxy.ts +68 -57
- package/src/helpers/subscription.ts +7 -6
- package/src/helpers/value.ts +30 -20
- package/src/index.ts +1 -0
- package/src/models.ts +47 -43
- package/src/value/array.ts +81 -64
- package/src/value/computed.ts +12 -16
- package/src/value/readonly.ts +38 -29
- package/src/value/signal.ts +20 -20
- package/src/value/store.ts +4 -7
package/dist/value/array.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { METHODS_AFFECTING_LENGTH, METHODS_UPDATE, NAME_ARRAY, NAME_MORA, PROPERTY_LENGTH, SYMBOL_STATE } from "../constants.mjs";
|
|
2
|
-
import { emitValue, equalArrays, getStringValue } from "../helpers/value.mjs";
|
|
2
|
+
import { emitValue, equalArrays, getJsonValue, getStringValue } from "../helpers/value.mjs";
|
|
3
3
|
import { getState } from "../helpers/misc.mjs";
|
|
4
4
|
import { subscribeToProxy } from "../helpers/subscription.mjs";
|
|
5
5
|
import { computed } from "./computed.mjs";
|
|
6
6
|
import { emitProxyValues, getValueInProxy, peekValueInProxy, setProxyValue, setValueInProxy, updateProxyValue } from "../helpers/proxy.mjs";
|
|
7
|
-
import {
|
|
7
|
+
import { getReadonlySignal } from "./readonly.mjs";
|
|
8
8
|
import { signal } from "./signal.mjs";
|
|
9
9
|
import { select } from "@oscarpalmer/atoms/array";
|
|
10
10
|
import { filter } from "@oscarpalmer/atoms/array/filter";
|
|
@@ -19,64 +19,76 @@ function ReactiveArray(value, options) {
|
|
|
19
19
|
get: (target, property) => METHODS_UPDATE.has(property) ? updateArray(this, property, target) : Reflect.get(target, property),
|
|
20
20
|
set: (target, property, value) => setValueInProxy(this, target, property, value)
|
|
21
21
|
});
|
|
22
|
-
Object.defineProperty(this, PROPERTY_LENGTH, {
|
|
23
|
-
enumerable: true,
|
|
24
|
-
get: () => this[SYMBOL_STATE].length.get(),
|
|
25
|
-
set: (value) => setArrayLength(this[SYMBOL_STATE], value)
|
|
26
|
-
});
|
|
27
22
|
setProxyValue.call(this, value);
|
|
28
23
|
}
|
|
29
24
|
ReactiveArray.prototype[NAME_MORA] = NAME_ARRAY;
|
|
30
|
-
ReactiveArray.prototype
|
|
25
|
+
Object.defineProperty(ReactiveArray.prototype, PROPERTY_LENGTH, {
|
|
26
|
+
enumerable: true,
|
|
27
|
+
get: getArrayLength,
|
|
28
|
+
set: setArrayLength
|
|
29
|
+
});
|
|
30
|
+
ReactiveArray.prototype.asReadonly = getReadonlySignal;
|
|
31
31
|
ReactiveArray.prototype.at = getArrayValues;
|
|
32
|
+
ReactiveArray.prototype.clear = clearArrayValues;
|
|
33
|
+
ReactiveArray.prototype.filter = filterArrayValues;
|
|
32
34
|
ReactiveArray.prototype.get = getArrayValues;
|
|
35
|
+
ReactiveArray.prototype.map = mapArrayValues;
|
|
33
36
|
ReactiveArray.prototype.notify = emitProxyValues;
|
|
34
37
|
ReactiveArray.prototype.peek = peekArrayValue;
|
|
38
|
+
ReactiveArray.prototype.pop = popArrayValue;
|
|
39
|
+
ReactiveArray.prototype.push = pushArrayValues;
|
|
40
|
+
ReactiveArray.prototype.select = selectArrayValues;
|
|
41
|
+
ReactiveArray.prototype.shift = shiftArrayValue;
|
|
35
42
|
ReactiveArray.prototype.set = setProxyValue;
|
|
43
|
+
ReactiveArray.prototype.splice = spliceArrayValues;
|
|
36
44
|
ReactiveArray.prototype.subscribe = subscribeToProxy;
|
|
37
45
|
ReactiveArray.prototype.toString = getStringValue;
|
|
46
|
+
ReactiveArray.prototype.toJSON = getJsonValue;
|
|
47
|
+
ReactiveArray.prototype.unshift = unshiftArrayValues;
|
|
38
48
|
ReactiveArray.prototype.update = updateProxyValue;
|
|
39
|
-
ReactiveArray.prototype.clear = function() {
|
|
40
|
-
this[SYMBOL_STATE].value.length = 0;
|
|
41
|
-
};
|
|
42
|
-
ReactiveArray.prototype.filter = function(callback) {
|
|
43
|
-
return computed(() => filter(getArrayValues.call(this), callback));
|
|
44
|
-
};
|
|
45
|
-
ReactiveArray.prototype.map = function(callback) {
|
|
46
|
-
return computed(() => getArrayValues.call(this).map(callback));
|
|
47
|
-
};
|
|
48
|
-
ReactiveArray.prototype.pop = function() {
|
|
49
|
-
return this[SYMBOL_STATE].value.pop();
|
|
50
|
-
};
|
|
51
|
-
ReactiveArray.prototype.push = function(...items) {
|
|
52
|
-
return this[SYMBOL_STATE].value.push(...items);
|
|
53
|
-
};
|
|
54
|
-
ReactiveArray.prototype.select = function(filter, map) {
|
|
55
|
-
return computed(() => select(getArrayValues.call(this), filter, map));
|
|
56
|
-
};
|
|
57
|
-
ReactiveArray.prototype.shift = function() {
|
|
58
|
-
return this[SYMBOL_STATE].value.shift();
|
|
59
|
-
};
|
|
60
|
-
ReactiveArray.prototype.splice = function(from, to, ...items) {
|
|
61
|
-
return this[SYMBOL_STATE].value.splice(from, to ?? this[SYMBOL_STATE].value.length, ...items);
|
|
62
|
-
};
|
|
63
|
-
ReactiveArray.prototype.toJSON = function() {
|
|
64
|
-
return this[SYMBOL_STATE].value;
|
|
65
|
-
};
|
|
66
|
-
ReactiveArray.prototype.unshift = function(...items) {
|
|
67
|
-
return this[SYMBOL_STATE].value.unshift(...items);
|
|
68
|
-
};
|
|
69
49
|
function array(value, options) {
|
|
70
50
|
return new ReactiveArray(value, options);
|
|
71
51
|
}
|
|
52
|
+
function clearArrayValues() {
|
|
53
|
+
this[SYMBOL_STATE].value.length = 0;
|
|
54
|
+
}
|
|
55
|
+
function filterArrayValues(callback) {
|
|
56
|
+
return computed(() => filter(getArrayValues.call(this), callback));
|
|
57
|
+
}
|
|
58
|
+
function getArrayLength() {
|
|
59
|
+
return this[SYMBOL_STATE].length.get();
|
|
60
|
+
}
|
|
72
61
|
function getArrayValues(value) {
|
|
73
62
|
return value === "length" ? this[SYMBOL_STATE].length.get() : getValueInProxy.call(this, value);
|
|
74
63
|
}
|
|
64
|
+
function mapArrayValues(callback) {
|
|
65
|
+
return computed(() => getArrayValues.call(this).map(callback));
|
|
66
|
+
}
|
|
75
67
|
function peekArrayValue(first, second) {
|
|
76
68
|
return first === "length" ? this[SYMBOL_STATE].length.peek() : peekValueInProxy.call(this, first, second);
|
|
77
69
|
}
|
|
78
|
-
function
|
|
79
|
-
|
|
70
|
+
function popArrayValue() {
|
|
71
|
+
return this[SYMBOL_STATE].value.pop();
|
|
72
|
+
}
|
|
73
|
+
function pushArrayValues(...items) {
|
|
74
|
+
return this[SYMBOL_STATE].value.push(...items);
|
|
75
|
+
}
|
|
76
|
+
function selectArrayValues(filter, map) {
|
|
77
|
+
return computed(() => select(getArrayValues.call(this), filter, map));
|
|
78
|
+
}
|
|
79
|
+
function setArrayLength(value) {
|
|
80
|
+
const values = this[SYMBOL_STATE].value;
|
|
81
|
+
if (typeof value === "number" && !Number.isNaN(value) && value >= 0 && value !== values.length) values.length = value;
|
|
82
|
+
}
|
|
83
|
+
function shiftArrayValue() {
|
|
84
|
+
return this[SYMBOL_STATE].value.shift();
|
|
85
|
+
}
|
|
86
|
+
function spliceArrayValues(from, to, ...items) {
|
|
87
|
+
const values = this[SYMBOL_STATE].value;
|
|
88
|
+
return values.splice(from, to ?? values.length, ...items);
|
|
89
|
+
}
|
|
90
|
+
function unshiftArrayValues(...items) {
|
|
91
|
+
return this[SYMBOL_STATE].value.unshift(...items);
|
|
80
92
|
}
|
|
81
93
|
function updateArray(instance, type, array) {
|
|
82
94
|
const state = instance[SYMBOL_STATE];
|
|
@@ -85,7 +97,7 @@ function updateArray(instance, type, array) {
|
|
|
85
97
|
const previousLength = array.length;
|
|
86
98
|
return (...args) => {
|
|
87
99
|
const result = array[type](...args);
|
|
88
|
-
if (affectsLength ? array.length !== previousLength : !equalArrays(
|
|
100
|
+
if (affectsLength ? array.length !== previousLength : !equalArrays(previousArray, array, state.equal)) {
|
|
89
101
|
emitValue(instance);
|
|
90
102
|
state.length.set(array.length);
|
|
91
103
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Computed, ComputedEffect, ReactiveOptions } from "../models.mjs";
|
|
1
|
+
import { Computed, ComputedEffect, InternalComputed, ReactiveOptions } from "../models.mjs";
|
|
2
2
|
import { GenericCallback } from "@oscarpalmer/atoms/models";
|
|
3
3
|
//#region src/value/computed.d.ts
|
|
4
4
|
declare function Computed(this: any, callback: GenericCallback, options?: ReactiveOptions<unknown>): void;
|
|
@@ -10,5 +10,5 @@ declare function Computed(this: any, callback: GenericCallback, options?: Reacti
|
|
|
10
10
|
* @returns Computed value
|
|
11
11
|
*/
|
|
12
12
|
export declare function computed<Value>(callback: () => Value | Promise<Value>, options?: ReactiveOptions<Value>): Computed<Value>;
|
|
13
|
-
export declare function internalComputed(callback: GenericCallback, options?: ReactiveOptions<unknown>): [
|
|
13
|
+
export declare function internalComputed(callback: GenericCallback, options?: ReactiveOptions<unknown>): [InternalComputed, ComputedEffect];
|
|
14
14
|
//#endregion
|
package/dist/value/computed.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ACTIVE, BATCH, NAME_COMPUTED, NAME_MORA, SUBSCRIPTION_TYPES, SUBSCRIPTION_TYPES_COPY, SYMBOL_EFFECT, SYMBOL_STATE } from "../constants.mjs";
|
|
2
2
|
import { internalEffect, runEffect } from "../effect.mjs";
|
|
3
|
-
import { getStringValue,
|
|
3
|
+
import { getJsonValue, getStringValue, handleSignal, peekSignalValue } from "../helpers/value.mjs";
|
|
4
4
|
import { flushHandlers } from "../batch.mjs";
|
|
5
5
|
import { getState } from "../helpers/misc.mjs";
|
|
6
6
|
import { subscribeToSignal } from "../helpers/subscription.mjs";
|
|
@@ -13,10 +13,8 @@ Computed.prototype[NAME_MORA] = NAME_COMPUTED;
|
|
|
13
13
|
Computed.prototype.get = getComputedValue;
|
|
14
14
|
Computed.prototype.peek = peekSignalValue;
|
|
15
15
|
Computed.prototype.subscribe = subscribeToSignal;
|
|
16
|
+
Computed.prototype.toJSON = getJsonValue;
|
|
16
17
|
Computed.prototype.toString = getStringValue;
|
|
17
|
-
Computed.prototype.toJSON = function() {
|
|
18
|
-
return this[SYMBOL_STATE].value;
|
|
19
|
-
};
|
|
20
18
|
/**
|
|
21
19
|
* Create a computed value
|
|
22
20
|
*
|
|
@@ -41,7 +39,7 @@ function getComputedEffect(instance, callback) {
|
|
|
41
39
|
if (fx.dirty) {
|
|
42
40
|
const previousComputed = ACTIVE.computed;
|
|
43
41
|
ACTIVE.computed = fx;
|
|
44
|
-
|
|
42
|
+
handleSignal(instance, callback, setAndEmit, () => {
|
|
45
43
|
ACTIVE.computed = previousComputed;
|
|
46
44
|
});
|
|
47
45
|
fx.dirty = false;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { InternalSignal, ReadonlyFrozenSignal, ReadonlySignal, SignalState } from "../models.mjs";
|
|
2
2
|
//#region src/value/readonly.d.ts
|
|
3
|
-
export declare function getReadonlyInstance
|
|
4
|
-
export declare function getReadonlySignal(
|
|
3
|
+
export declare function getReadonlyInstance(state: SignalState, frozen: boolean): ReadonlySignal<unknown> | ReadonlyFrozenSignal<unknown>;
|
|
4
|
+
export declare function getReadonlySignal<Value>(this: InternalSignal, frozen?: never): ReadonlySignal<Value>;
|
|
5
5
|
//#endregion
|
package/dist/value/readonly.mjs
CHANGED
|
@@ -1,40 +1,37 @@
|
|
|
1
1
|
import { NAME_MORA, NAME_READONLY, SUBSCRIPTION_TYPE_FROZEN, SUBSCRIPTION_TYPE_ORIGINAL, SYMBOL_STATE } from "../constants.mjs";
|
|
2
|
-
import { getFrozenValue, getSignalValue, getStringValue, peekSignalValue } from "../helpers/value.mjs";
|
|
2
|
+
import { getFrozenValue, getJsonValue, getSignalValue, getStringValue, peekSignalValue } from "../helpers/value.mjs";
|
|
3
3
|
import { subscribeToReadonly } from "../helpers/subscription.mjs";
|
|
4
4
|
//#region src/value/readonly.ts
|
|
5
5
|
function Readonly(state, frozen) {
|
|
6
|
+
this[SUBSCRIPTION_TYPE_FROZEN] = frozen;
|
|
6
7
|
this[SYMBOL_STATE] = state;
|
|
7
|
-
Object.defineProperty(this, SUBSCRIPTION_TYPE_FROZEN, {
|
|
8
|
-
enumerable: true,
|
|
9
|
-
value: frozen
|
|
10
|
-
});
|
|
11
8
|
}
|
|
12
9
|
Readonly.prototype[NAME_MORA] = NAME_READONLY;
|
|
10
|
+
Readonly.prototype.get = getReadonlyValue;
|
|
11
|
+
Readonly.prototype.peek = peekReadonlyValue;
|
|
13
12
|
Readonly.prototype.subscribe = subscribeToReadonly;
|
|
13
|
+
Readonly.prototype.toJSON = getJsonValue;
|
|
14
14
|
Readonly.prototype.toString = getStringValue;
|
|
15
|
-
|
|
16
|
-
return
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return getReadonlyValue(this, true, this[SUBSCRIPTION_TYPE_FROZEN], copy);
|
|
20
|
-
};
|
|
21
|
-
Readonly.prototype.toJSON = function() {
|
|
22
|
-
return this[SYMBOL_STATE].value;
|
|
23
|
-
};
|
|
24
|
-
function getReadonlyInstance(frozen) {
|
|
15
|
+
function getReadonlyInstance(state, frozen) {
|
|
16
|
+
return new Readonly(state, frozen);
|
|
17
|
+
}
|
|
18
|
+
function getReadonlySignal(frozen) {
|
|
25
19
|
const key = frozen === true ? SUBSCRIPTION_TYPE_FROZEN : SUBSCRIPTION_TYPE_ORIGINAL;
|
|
26
20
|
this[SYMBOL_STATE].readonlies ??= {};
|
|
27
|
-
this[SYMBOL_STATE].readonlies[key] ??=
|
|
21
|
+
this[SYMBOL_STATE].readonlies[key] ??= getReadonlyInstance(this[SYMBOL_STATE], frozen === true);
|
|
28
22
|
return this[SYMBOL_STATE].readonlies[key];
|
|
29
23
|
}
|
|
30
|
-
function
|
|
31
|
-
return
|
|
24
|
+
function getReadonlyValue() {
|
|
25
|
+
return handleReadonlyValue(this, false, this[SUBSCRIPTION_TYPE_FROZEN]);
|
|
32
26
|
}
|
|
33
|
-
function
|
|
27
|
+
function handleReadonlyValue(instance, peek, frozen, copy) {
|
|
34
28
|
let value;
|
|
35
29
|
if (peek) value = peekSignalValue.call(instance, copy === true);
|
|
36
30
|
else value = getSignalValue.call(instance);
|
|
37
31
|
return frozen ? getFrozenValue(value) : value;
|
|
38
32
|
}
|
|
33
|
+
function peekReadonlyValue(copy) {
|
|
34
|
+
return handleReadonlyValue(this, true, this[SUBSCRIPTION_TYPE_FROZEN], copy);
|
|
35
|
+
}
|
|
39
36
|
//#endregion
|
|
40
37
|
export { getReadonlyInstance, getReadonlySignal };
|
package/dist/value/signal.mjs
CHANGED
|
@@ -1,28 +1,22 @@
|
|
|
1
1
|
import { NAME_MORA, NAME_SIGNAL, SYMBOL_STATE } from "../constants.mjs";
|
|
2
|
-
import { emitValue, getSignalValue, getStringValue,
|
|
2
|
+
import { emitValue, getJsonValue, getSignalValue, getStringValue, handleSignal, peekSignalValue, updateSignal } from "../helpers/value.mjs";
|
|
3
3
|
import { getState } from "../helpers/misc.mjs";
|
|
4
4
|
import { subscribeToSignal } from "../helpers/subscription.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { getReadonlySignal } from "./readonly.mjs";
|
|
6
6
|
//#region src/value/signal.ts
|
|
7
7
|
function Signal(value, options) {
|
|
8
8
|
this[SYMBOL_STATE] = getState(void 0, options);
|
|
9
|
-
|
|
9
|
+
handleSignal(this, value, setAndEmit);
|
|
10
10
|
}
|
|
11
11
|
Signal.prototype[NAME_MORA] = NAME_SIGNAL;
|
|
12
|
-
Signal.prototype.asReadonly =
|
|
12
|
+
Signal.prototype.asReadonly = getReadonlySignal;
|
|
13
13
|
Signal.prototype.get = getSignalValue;
|
|
14
14
|
Signal.prototype.peek = peekSignalValue;
|
|
15
|
+
Signal.prototype.set = setSignalValue;
|
|
15
16
|
Signal.prototype.subscribe = subscribeToSignal;
|
|
16
17
|
Signal.prototype.toString = getStringValue;
|
|
17
|
-
Signal.prototype.
|
|
18
|
-
|
|
19
|
-
};
|
|
20
|
-
Signal.prototype.toJSON = function() {
|
|
21
|
-
return this[SYMBOL_STATE].value;
|
|
22
|
-
};
|
|
23
|
-
Signal.prototype.update = function(callback) {
|
|
24
|
-
return updateSignalValue(this, callback, setAndEmit);
|
|
25
|
-
};
|
|
18
|
+
Signal.prototype.toJSON = getJsonValue;
|
|
19
|
+
Signal.prototype.update = updateSignalValue;
|
|
26
20
|
function setAndEmit(instance, value) {
|
|
27
21
|
const state = instance[SYMBOL_STATE];
|
|
28
22
|
if (!(state.equal ?? Object.is)(state.value, value)) {
|
|
@@ -30,8 +24,14 @@ function setAndEmit(instance, value) {
|
|
|
30
24
|
emitValue(instance);
|
|
31
25
|
}
|
|
32
26
|
}
|
|
27
|
+
function setSignalValue(value) {
|
|
28
|
+
handleSignal(this, value, setAndEmit);
|
|
29
|
+
}
|
|
33
30
|
function signal(value, options) {
|
|
34
31
|
return new Signal(value, options);
|
|
35
32
|
}
|
|
33
|
+
function updateSignalValue(callback) {
|
|
34
|
+
updateSignal(this, callback, setAndEmit);
|
|
35
|
+
}
|
|
36
36
|
//#endregion
|
|
37
37
|
export { signal };
|
package/dist/value/store.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { NAME_MORA, NAME_STORE, SYMBOL_STATE } from "../constants.mjs";
|
|
2
|
-
import { getStringValue } from "../helpers/value.mjs";
|
|
2
|
+
import { getJsonValue, getStringValue } from "../helpers/value.mjs";
|
|
3
3
|
import { getState } from "../helpers/misc.mjs";
|
|
4
4
|
import { subscribeToProxy } from "../helpers/subscription.mjs";
|
|
5
5
|
import { emitProxyValues, getValueInProxy, peekValueInProxy, setProxyValue, setValueInProxy, updateProxyValue } from "../helpers/proxy.mjs";
|
|
6
|
-
import {
|
|
6
|
+
import { getReadonlySignal } from "./readonly.mjs";
|
|
7
7
|
//#region src/value/store.ts
|
|
8
8
|
function ReactiveStore(value, options) {
|
|
9
9
|
this[SYMBOL_STATE] = {
|
|
@@ -14,17 +14,15 @@ function ReactiveStore(value, options) {
|
|
|
14
14
|
setProxyValue.call(this, value);
|
|
15
15
|
}
|
|
16
16
|
ReactiveStore.prototype[NAME_MORA] = NAME_STORE;
|
|
17
|
-
ReactiveStore.prototype.asReadonly =
|
|
17
|
+
ReactiveStore.prototype.asReadonly = getReadonlySignal;
|
|
18
18
|
ReactiveStore.prototype.get = getValueInProxy;
|
|
19
19
|
ReactiveStore.prototype.notify = emitProxyValues;
|
|
20
20
|
ReactiveStore.prototype.peek = peekValueInProxy;
|
|
21
21
|
ReactiveStore.prototype.set = setProxyValue;
|
|
22
22
|
ReactiveStore.prototype.subscribe = subscribeToProxy;
|
|
23
|
+
ReactiveStore.prototype.toJSON = getJsonValue;
|
|
23
24
|
ReactiveStore.prototype.toString = getStringValue;
|
|
24
25
|
ReactiveStore.prototype.update = updateProxyValue;
|
|
25
|
-
ReactiveStore.prototype.toJSON = function() {
|
|
26
|
-
return this[SYMBOL_STATE].value;
|
|
27
|
-
};
|
|
28
26
|
function store(value, options) {
|
|
29
27
|
return new ReactiveStore(value, options);
|
|
30
28
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oscarpalmer/mora",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.0",
|
|
4
4
|
"description": "Signals and stuff…",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"reactive",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"test:leak": "vpx vp test run --detect-async-leaks --coverage"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@oscarpalmer/atoms": "^0.
|
|
42
|
+
"@oscarpalmer/atoms": "^0.203"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/node": "^26.5",
|
package/src/batch.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {BATCH} from './constants';
|
|
2
2
|
import {runEffect} from './effect';
|
|
3
3
|
import {getFrozenValue, peekSignalValue} from './helpers/value';
|
|
4
|
-
import type {
|
|
4
|
+
import type {StoredSubscription} from './models';
|
|
5
5
|
|
|
6
6
|
// #region Functions
|
|
7
7
|
|
|
@@ -30,7 +30,7 @@ export function flushHandlers(): void {
|
|
|
30
30
|
: peekSignalValue.call(subscription.instance, subscription.copy),
|
|
31
31
|
);
|
|
32
32
|
} else {
|
|
33
|
-
runEffect(handler
|
|
33
|
+
runEffect(handler);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
}
|
package/src/constants.ts
CHANGED
|
@@ -16,9 +16,14 @@ export const BATCH: Batch = {
|
|
|
16
16
|
handlers: new Map(),
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
export const METHODS_AFFECTING_LENGTH = new Set<string>([
|
|
19
|
+
export const METHODS_AFFECTING_LENGTH = new Set<string | symbol>([
|
|
20
|
+
'pop',
|
|
21
|
+
'push',
|
|
22
|
+
'shift',
|
|
23
|
+
'unshift',
|
|
24
|
+
]);
|
|
20
25
|
|
|
21
|
-
export const METHODS_UPDATE = new Set<string>([
|
|
26
|
+
export const METHODS_UPDATE = new Set<string | symbol>([
|
|
22
27
|
...METHODS_AFFECTING_LENGTH,
|
|
23
28
|
'copyWithin',
|
|
24
29
|
'fill',
|
package/src/helpers/is.ts
CHANGED
|
@@ -46,9 +46,7 @@ function isMora<Instance>(value: unknown, name: string | Set<string>): value is
|
|
|
46
46
|
typeof value === 'object' &&
|
|
47
47
|
value != null &&
|
|
48
48
|
NAME_MORA in value &&
|
|
49
|
-
(typeof name === 'string'
|
|
50
|
-
? (value as PlainObject)[NAME_MORA] === name
|
|
51
|
-
: name.has((value as PlainObject)[NAME_MORA] as never))
|
|
49
|
+
(typeof name === 'string' ? value[NAME_MORA] === name : name.has(value[NAME_MORA] as never))
|
|
52
50
|
);
|
|
53
51
|
}
|
|
54
52
|
|
package/src/helpers/proxy.ts
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import {isKey, isPlainObject} from '@oscarpalmer/atoms/is';
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
ArrayOrPlainObject,
|
|
4
|
+
GenericCallback,
|
|
5
|
+
Key,
|
|
6
|
+
PlainObject,
|
|
7
|
+
} from '@oscarpalmer/atoms/models';
|
|
3
8
|
import {startBatch, stopBatch} from '../batch';
|
|
4
9
|
import {PROPERTY_LENGTH, SYMBOL_STATE} from '../constants';
|
|
5
|
-
import type {
|
|
6
|
-
Computed,
|
|
7
|
-
ReactiveArray,
|
|
8
|
-
ReactiveProxyState,
|
|
9
|
-
ReactiveStore,
|
|
10
|
-
InternalProxy,
|
|
11
|
-
} from '../models';
|
|
10
|
+
import type {InternalArray, InternalComputed, InternalStore, ReactiveProxyState} from '../models';
|
|
12
11
|
import {internalComputed} from '../value/computed';
|
|
13
12
|
import {emitValue, getSignalValue, peekSignalValue} from './value';
|
|
14
13
|
|
|
15
14
|
// #region Functions
|
|
16
15
|
|
|
17
|
-
export function emitProxyValues(this:
|
|
16
|
+
export function emitProxyValues(this: InternalArray | InternalStore): void {
|
|
18
17
|
const state = this[SYMBOL_STATE];
|
|
19
18
|
|
|
20
19
|
state.mapped ??= new Map();
|
|
@@ -30,10 +29,10 @@ export function emitProxyValues(this: InternalProxy): void {
|
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
export function getReactiveValueInProxy(
|
|
33
|
-
instance:
|
|
32
|
+
instance: InternalArray | InternalStore,
|
|
34
33
|
key: Key,
|
|
35
|
-
):
|
|
36
|
-
const state =
|
|
34
|
+
): InternalComputed {
|
|
35
|
+
const state = instance[SYMBOL_STATE];
|
|
37
36
|
|
|
38
37
|
state.mapped ??= new Map();
|
|
39
38
|
|
|
@@ -54,19 +53,29 @@ export function getReactiveValueInProxy(
|
|
|
54
53
|
return item[0];
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
export function getValueInProxy(this:
|
|
56
|
+
export function getValueInProxy(this: InternalArray | InternalStore, first?: unknown): unknown {
|
|
57
|
+
let signal: InternalComputed | undefined;
|
|
58
|
+
|
|
58
59
|
if (this[SYMBOL_STATE].isArray ? typeof first === 'number' : isKey(first)) {
|
|
59
|
-
|
|
60
|
+
signal = getReactiveValueInProxy(this, first as Key);
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
return getSignalValue.call(this);
|
|
63
|
+
return getSignalValue.call(signal ?? this);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function isProxyKey(isArray: boolean, value: unknown): value is Key {
|
|
67
|
+
return isArray ? typeof value === 'number' : isKey(value);
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
function isProxyObject(isArray: boolean, value: unknown): value is ArrayOrPlainObject {
|
|
66
71
|
return value == null || (isArray ? Array.isArray(value) : isPlainObject(value));
|
|
67
72
|
}
|
|
68
73
|
|
|
69
|
-
export function peekValueInProxy(
|
|
74
|
+
export function peekValueInProxy(
|
|
75
|
+
this: InternalArray | InternalStore,
|
|
76
|
+
first?: unknown,
|
|
77
|
+
second?: boolean,
|
|
78
|
+
): unknown {
|
|
70
79
|
const state = this[SYMBOL_STATE];
|
|
71
80
|
|
|
72
81
|
let value: unknown;
|
|
@@ -84,40 +93,38 @@ export function peekValueInProxy(this: InternalProxy, first?: unknown, second?:
|
|
|
84
93
|
|
|
85
94
|
function setProxyObject(state: ReactiveProxyState, value: unknown): void {
|
|
86
95
|
if (state.isArray) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
...((value ?? []) as unknown[]),
|
|
91
|
-
);
|
|
96
|
+
const values = state.value as unknown[];
|
|
97
|
+
|
|
98
|
+
values.splice(0, values.length, ...((value ?? []) as unknown[]));
|
|
92
99
|
|
|
93
100
|
return;
|
|
94
101
|
}
|
|
95
102
|
|
|
96
103
|
startBatch();
|
|
97
104
|
|
|
98
|
-
const
|
|
99
|
-
const
|
|
105
|
+
const current = state.value as PlainObject;
|
|
106
|
+
const next = (value as Record<string, unknown>) ?? {};
|
|
100
107
|
|
|
101
|
-
const
|
|
102
|
-
const
|
|
108
|
+
const currentKeys = Object.keys(current);
|
|
109
|
+
const nextKeys = Object.keys(next);
|
|
103
110
|
|
|
104
|
-
let {length} =
|
|
111
|
+
let {length} = currentKeys;
|
|
105
112
|
|
|
106
113
|
for (let index = 0; index < length; index += 1) {
|
|
107
|
-
const key =
|
|
114
|
+
const key = currentKeys[index];
|
|
108
115
|
|
|
109
|
-
|
|
116
|
+
current[key] = nextKeys.includes(key) ? next[key] : undefined;
|
|
110
117
|
}
|
|
111
118
|
|
|
112
|
-
length =
|
|
119
|
+
length = nextKeys.length;
|
|
113
120
|
|
|
114
121
|
for (let index = 0; index < length; index += 1) {
|
|
115
|
-
const key =
|
|
122
|
+
const key = nextKeys[index];
|
|
116
123
|
|
|
117
|
-
if (!
|
|
118
|
-
const keyedValue =
|
|
124
|
+
if (!currentKeys.includes(key)) {
|
|
125
|
+
const keyedValue = next[key];
|
|
119
126
|
|
|
120
|
-
|
|
127
|
+
current[key] = keyedValue;
|
|
121
128
|
}
|
|
122
129
|
}
|
|
123
130
|
|
|
@@ -131,18 +138,22 @@ function setProxyProperty(state: ReactiveProxyState, property: unknown, value: u
|
|
|
131
138
|
return;
|
|
132
139
|
}
|
|
133
140
|
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
141
|
+
const array = state.value as unknown[];
|
|
142
|
+
const index = property as number;
|
|
143
|
+
|
|
144
|
+
const actual = index < 0 ? array.length + index : index;
|
|
138
145
|
|
|
139
146
|
if (actual > -1) {
|
|
140
|
-
|
|
147
|
+
array[actual] = value;
|
|
141
148
|
}
|
|
142
149
|
}
|
|
143
150
|
|
|
144
|
-
export function setProxyValue(
|
|
145
|
-
|
|
151
|
+
export function setProxyValue(
|
|
152
|
+
this: InternalArray | InternalStore,
|
|
153
|
+
first?: unknown,
|
|
154
|
+
second?: unknown,
|
|
155
|
+
): void {
|
|
156
|
+
const state = this[SYMBOL_STATE];
|
|
146
157
|
|
|
147
158
|
if (state.isArray && first === PROPERTY_LENGTH) {
|
|
148
159
|
(state.value as unknown[]).length = second as number;
|
|
@@ -156,55 +167,55 @@ export function setProxyValue(this: InternalProxy, first?: unknown, second?: unk
|
|
|
156
167
|
return;
|
|
157
168
|
}
|
|
158
169
|
|
|
159
|
-
const
|
|
170
|
+
const keyed = isProxyKey(state.isArray, first);
|
|
160
171
|
|
|
161
|
-
if (state.isArray &&
|
|
172
|
+
if (state.isArray && keyed && Number.isNaN(first)) {
|
|
162
173
|
return;
|
|
163
174
|
}
|
|
164
175
|
|
|
165
|
-
let actual =
|
|
176
|
+
let actual = keyed ? second : first;
|
|
166
177
|
|
|
167
178
|
if (typeof actual === 'function') {
|
|
168
179
|
try {
|
|
169
|
-
actual = (actual as
|
|
180
|
+
actual = (actual as GenericCallback)();
|
|
170
181
|
} catch {
|
|
171
182
|
return;
|
|
172
183
|
}
|
|
173
184
|
}
|
|
174
185
|
|
|
175
186
|
if (actual instanceof Promise) {
|
|
176
|
-
if (
|
|
187
|
+
if (keyed) {
|
|
177
188
|
state.promises ??= new Map();
|
|
178
189
|
|
|
179
|
-
state.promises.set(first
|
|
190
|
+
state.promises.set(first, actual as Promise<never>);
|
|
180
191
|
} else {
|
|
181
192
|
state.promise = actual as Promise<never>;
|
|
182
193
|
}
|
|
183
194
|
|
|
184
195
|
void actual
|
|
185
196
|
.then(value => {
|
|
186
|
-
if (
|
|
187
|
-
state.promises
|
|
197
|
+
if (keyed && state.promises?.get(first) === actual) {
|
|
198
|
+
state.promises?.delete(first);
|
|
188
199
|
|
|
189
200
|
setProxyProperty(state, first, value);
|
|
190
201
|
|
|
191
202
|
return;
|
|
192
203
|
}
|
|
193
204
|
|
|
194
|
-
if (!
|
|
205
|
+
if (!keyed && isProxyObject(state.isArray, value) && state.promise === actual) {
|
|
195
206
|
state.promise = undefined;
|
|
196
207
|
|
|
197
208
|
setProxyObject(state, value);
|
|
198
209
|
}
|
|
199
210
|
})
|
|
200
211
|
.catch(() => {
|
|
201
|
-
if (
|
|
202
|
-
state.promises
|
|
203
|
-
} else if (!
|
|
212
|
+
if (keyed && state.promises?.get(first) === actual) {
|
|
213
|
+
state.promises?.delete(first);
|
|
214
|
+
} else if (!keyed && state.promise === actual) {
|
|
204
215
|
state.promise = undefined;
|
|
205
216
|
}
|
|
206
217
|
});
|
|
207
|
-
} else if (
|
|
218
|
+
} else if (keyed) {
|
|
208
219
|
setProxyProperty(state, first, actual);
|
|
209
220
|
} else if (isProxyObject(state.isArray, actual)) {
|
|
210
221
|
setProxyObject(state, actual);
|
|
@@ -212,7 +223,7 @@ export function setProxyValue(this: InternalProxy, first?: unknown, second?: unk
|
|
|
212
223
|
}
|
|
213
224
|
|
|
214
225
|
export function setValueInProxy(
|
|
215
|
-
instance:
|
|
226
|
+
instance: InternalArray | InternalStore,
|
|
216
227
|
target: object,
|
|
217
228
|
property: PropertyKey,
|
|
218
229
|
value: unknown,
|
|
@@ -228,9 +239,9 @@ export function setValueInProxy(
|
|
|
228
239
|
}
|
|
229
240
|
}
|
|
230
241
|
|
|
231
|
-
const previous = Reflect.get(target
|
|
242
|
+
const previous = Reflect.get(target, property);
|
|
232
243
|
|
|
233
|
-
if (!(state.equal ?? Object.is)(previous
|
|
244
|
+
if (!(state.equal ?? Object.is)(previous, value)) {
|
|
234
245
|
Reflect.set(target, property, value);
|
|
235
246
|
|
|
236
247
|
emitValue(instance);
|
|
@@ -243,7 +254,7 @@ export function setValueInProxy(
|
|
|
243
254
|
return true;
|
|
244
255
|
}
|
|
245
256
|
|
|
246
|
-
export function updateProxyValue(this:
|
|
257
|
+
export function updateProxyValue(this: InternalArray | InternalStore, callback: unknown): void {
|
|
247
258
|
if (typeof callback !== 'function') {
|
|
248
259
|
throw new TypeError('Callback must be a function');
|
|
249
260
|
}
|