@oscarpalmer/mora 0.15.0 → 0.16.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/batch.cjs +3 -3
- package/dist/batch.js +3 -3
- package/dist/helpers/value.cjs +44 -8
- package/dist/helpers/value.js +45 -9
- package/dist/mora.full.js +56 -49
- package/dist/value/array.cjs +9 -4
- package/dist/value/array.js +8 -3
- package/dist/value/computed.cjs +1 -1
- package/dist/value/computed.js +1 -1
- package/dist/value/signal.cjs +4 -1
- package/dist/value/signal.js +5 -2
- package/package.json +3 -3
- package/src/batch.ts +2 -2
- package/src/helpers/is.ts +1 -1
- package/src/helpers/value.ts +57 -13
- package/src/value/array.ts +9 -3
- package/src/value/computed.ts +2 -2
- package/src/value/signal.ts +6 -2
- package/types/batch.d.cts +1 -1
- package/types/batch.d.ts +1 -1
- package/types/helpers/is.d.cts +4 -0
- package/types/helpers/is.d.ts +1 -1
- package/types/helpers/value.d.cts +3 -1
- package/types/helpers/value.d.ts +3 -1
- package/types/index.d.cts +4 -0
- package/types/value/array.d.cts +4 -0
- package/types/value/array.d.ts +4 -0
- package/types/value/computed.d.ts +1 -2
- package/dist/helpers/emit.cjs +0 -42
- package/dist/helpers/emit.js +0 -42
- package/src/helpers/emit.ts +0 -52
- package/types/helpers/emit.d.cts +0 -63
- package/types/helpers/emit.d.ts +0 -3
package/dist/batch.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const effect = require("./effect.cjs");
|
|
4
4
|
const helpers_is = require("./helpers/is.cjs");
|
|
5
|
-
function
|
|
5
|
+
function flushHandlers() {
|
|
6
6
|
while (exports.batchDepth === 0 && batchedHandlers.size > 0) {
|
|
7
7
|
const handlers = [...batchedHandlers];
|
|
8
8
|
batchedHandlers.clear();
|
|
@@ -22,11 +22,11 @@ function stopBatch() {
|
|
|
22
22
|
if (exports.batchDepth > 0) {
|
|
23
23
|
exports.batchDepth -= 1;
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
flushHandlers();
|
|
26
26
|
}
|
|
27
27
|
const batchedHandlers = /* @__PURE__ */ new Set();
|
|
28
28
|
exports.batchDepth = 0;
|
|
29
29
|
exports.batchedHandlers = batchedHandlers;
|
|
30
|
-
exports.
|
|
30
|
+
exports.flushHandlers = flushHandlers;
|
|
31
31
|
exports.startBatch = startBatch;
|
|
32
32
|
exports.stopBatch = stopBatch;
|
package/dist/batch.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { runEffect } from "./effect.js";
|
|
2
2
|
import { isEffect } from "./helpers/is.js";
|
|
3
|
-
function
|
|
3
|
+
function flushHandlers() {
|
|
4
4
|
while (batchDepth === 0 && batchedHandlers.size > 0) {
|
|
5
5
|
const handlers = [...batchedHandlers];
|
|
6
6
|
batchedHandlers.clear();
|
|
@@ -20,14 +20,14 @@ function stopBatch() {
|
|
|
20
20
|
if (batchDepth > 0) {
|
|
21
21
|
batchDepth -= 1;
|
|
22
22
|
}
|
|
23
|
-
|
|
23
|
+
flushHandlers();
|
|
24
24
|
}
|
|
25
25
|
const batchedHandlers = /* @__PURE__ */ new Set();
|
|
26
26
|
let batchDepth = 0;
|
|
27
27
|
export {
|
|
28
28
|
batchDepth,
|
|
29
29
|
batchedHandlers,
|
|
30
|
-
|
|
30
|
+
flushHandlers,
|
|
31
31
|
startBatch,
|
|
32
32
|
stopBatch
|
|
33
33
|
};
|
package/dist/helpers/value.cjs
CHANGED
|
@@ -1,8 +1,48 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const batch = require("../batch.cjs");
|
|
3
4
|
const effect = require("../effect.cjs");
|
|
4
5
|
const value_computed = require("../value/computed.cjs");
|
|
5
|
-
|
|
6
|
+
function differentArrays(first, second) {
|
|
7
|
+
let { length } = first;
|
|
8
|
+
if (length !== second.length) {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
let offset = 0;
|
|
12
|
+
if (length >= 100) {
|
|
13
|
+
offset = Math.round(length / 10);
|
|
14
|
+
offset = offset > 25 ? 25 : offset;
|
|
15
|
+
for (let index = 0; index < offset; index += 1) {
|
|
16
|
+
if (!Object.is(first[index], second[index])) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
length -= offset;
|
|
22
|
+
for (let index = offset; index < length; index += 1) {
|
|
23
|
+
if (!Object.is(first[index], second[index])) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
function differentValues(first, second) {
|
|
30
|
+
return Array.isArray(first) && Array.isArray(second) ? differentArrays(first, second) : !Object.is(first, second);
|
|
31
|
+
}
|
|
32
|
+
function emitValue(state) {
|
|
33
|
+
for (const computed of state.computeds) {
|
|
34
|
+
computed.effect.dirty = true;
|
|
35
|
+
}
|
|
36
|
+
for (const effect2 of state.effects) {
|
|
37
|
+
batch.batchedHandlers.add(effect2);
|
|
38
|
+
}
|
|
39
|
+
for (const [, subscription] of state.subscriptions) {
|
|
40
|
+
batch.batchedHandlers.add(subscription);
|
|
41
|
+
}
|
|
42
|
+
if (batch.batchDepth === 0) {
|
|
43
|
+
batch.flushHandlers();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
6
46
|
function getValue(state) {
|
|
7
47
|
if (value_computed.activeComputed != null) {
|
|
8
48
|
state.computeds.add(value_computed.activeComputed);
|
|
@@ -12,11 +52,7 @@ function getValue(state) {
|
|
|
12
52
|
}
|
|
13
53
|
return state.value;
|
|
14
54
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
helpers_emit.emitValue(state);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
55
|
+
exports.differentArrays = differentArrays;
|
|
56
|
+
exports.differentValues = differentValues;
|
|
57
|
+
exports.emitValue = emitValue;
|
|
21
58
|
exports.getValue = getValue;
|
|
22
|
-
exports.setValue = setValue;
|
package/dist/helpers/value.js
CHANGED
|
@@ -1,6 +1,46 @@
|
|
|
1
|
+
import { batchedHandlers, batchDepth, flushHandlers } from "../batch.js";
|
|
1
2
|
import { activeEffect } from "../effect.js";
|
|
2
3
|
import { activeComputed } from "../value/computed.js";
|
|
3
|
-
|
|
4
|
+
function differentArrays(first, second) {
|
|
5
|
+
let { length } = first;
|
|
6
|
+
if (length !== second.length) {
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
let offset = 0;
|
|
10
|
+
if (length >= 100) {
|
|
11
|
+
offset = Math.round(length / 10);
|
|
12
|
+
offset = offset > 25 ? 25 : offset;
|
|
13
|
+
for (let index = 0; index < offset; index += 1) {
|
|
14
|
+
if (!Object.is(first[index], second[index])) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
length -= offset;
|
|
20
|
+
for (let index = offset; index < length; index += 1) {
|
|
21
|
+
if (!Object.is(first[index], second[index])) {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
function differentValues(first, second) {
|
|
28
|
+
return Array.isArray(first) && Array.isArray(second) ? differentArrays(first, second) : !Object.is(first, second);
|
|
29
|
+
}
|
|
30
|
+
function emitValue(state) {
|
|
31
|
+
for (const computed of state.computeds) {
|
|
32
|
+
computed.effect.dirty = true;
|
|
33
|
+
}
|
|
34
|
+
for (const effect of state.effects) {
|
|
35
|
+
batchedHandlers.add(effect);
|
|
36
|
+
}
|
|
37
|
+
for (const [, subscription] of state.subscriptions) {
|
|
38
|
+
batchedHandlers.add(subscription);
|
|
39
|
+
}
|
|
40
|
+
if (batchDepth === 0) {
|
|
41
|
+
flushHandlers();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
4
44
|
function getValue(state) {
|
|
5
45
|
if (activeComputed != null) {
|
|
6
46
|
state.computeds.add(activeComputed);
|
|
@@ -10,13 +50,9 @@ function getValue(state) {
|
|
|
10
50
|
}
|
|
11
51
|
return state.value;
|
|
12
52
|
}
|
|
13
|
-
function setValue(state, value) {
|
|
14
|
-
if (!Object.is(state.value, value)) {
|
|
15
|
-
state.value = value;
|
|
16
|
-
emitValue(state);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
53
|
export {
|
|
20
|
-
|
|
21
|
-
|
|
54
|
+
differentArrays,
|
|
55
|
+
differentValues,
|
|
56
|
+
emitValue,
|
|
57
|
+
getValue
|
|
22
58
|
};
|
package/dist/mora.full.js
CHANGED
|
@@ -68,7 +68,7 @@ function effect(callback) {
|
|
|
68
68
|
}
|
|
69
69
|
let activeEffect;
|
|
70
70
|
|
|
71
|
-
function
|
|
71
|
+
function flushHandlers() {
|
|
72
72
|
while (batchDepth === 0 && batchedHandlers.size > 0) {
|
|
73
73
|
const handlers = [...batchedHandlers];
|
|
74
74
|
batchedHandlers.clear();
|
|
@@ -95,49 +95,11 @@ function stopBatch() {
|
|
|
95
95
|
if (batchDepth > 0) {
|
|
96
96
|
batchDepth -= 1;
|
|
97
97
|
}
|
|
98
|
-
|
|
98
|
+
flushHandlers();
|
|
99
99
|
}
|
|
100
100
|
const batchedHandlers = new Set();
|
|
101
101
|
let batchDepth = 0;
|
|
102
102
|
|
|
103
|
-
function emitArrayChanges(first, second) {
|
|
104
|
-
let { length } = first;
|
|
105
|
-
if (length !== second.length) {
|
|
106
|
-
return true;
|
|
107
|
-
}
|
|
108
|
-
let offset = 0;
|
|
109
|
-
if (length >= 100) {
|
|
110
|
-
offset = Math.round(length / 10);
|
|
111
|
-
offset = offset > 25 ? 25 : offset;
|
|
112
|
-
for (let index = 0; index < offset; index += 1) {
|
|
113
|
-
if (!Object.is(first[index], second[index])) {
|
|
114
|
-
return true;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
length -= offset;
|
|
119
|
-
for (let index = offset; index < length; index += 1) {
|
|
120
|
-
if (!Object.is(first[index], second[index])) {
|
|
121
|
-
return true;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
return false;
|
|
125
|
-
}
|
|
126
|
-
function emitValue(state) {
|
|
127
|
-
for (const computed of state.computeds) {
|
|
128
|
-
computed.effect.dirty = true;
|
|
129
|
-
}
|
|
130
|
-
for (const effect of state.effects) {
|
|
131
|
-
batchedHandlers.add(effect);
|
|
132
|
-
}
|
|
133
|
-
for (const [, subscription] of state.subscriptions) {
|
|
134
|
-
batchedHandlers.add(subscription);
|
|
135
|
-
}
|
|
136
|
-
if (batchDepth === 0) {
|
|
137
|
-
flushEffects();
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
103
|
class Subscription {
|
|
142
104
|
state;
|
|
143
105
|
callback;
|
|
@@ -245,7 +207,7 @@ class Computed extends Reactive {
|
|
|
245
207
|
* @inheritdoc
|
|
246
208
|
*/
|
|
247
209
|
get() {
|
|
248
|
-
if (activeComputed != null &&
|
|
210
|
+
if (activeComputed != null && this !== activeComputed) {
|
|
249
211
|
this.state.computeds.add(activeComputed);
|
|
250
212
|
}
|
|
251
213
|
if (activeEffect != null && activeEffect !== this.effect.instance) {
|
|
@@ -264,6 +226,48 @@ function computed(callback) {
|
|
|
264
226
|
return new Computed(callback);
|
|
265
227
|
}
|
|
266
228
|
|
|
229
|
+
function differentArrays(first, second) {
|
|
230
|
+
let { length } = first;
|
|
231
|
+
if (length !== second.length) {
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
let offset = 0;
|
|
235
|
+
if (length >= 100) {
|
|
236
|
+
offset = Math.round(length / 10);
|
|
237
|
+
offset = offset > 25 ? 25 : offset;
|
|
238
|
+
for (let index = 0; index < offset; index += 1) {
|
|
239
|
+
if (!Object.is(first[index], second[index])) {
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
length -= offset;
|
|
245
|
+
for (let index = offset; index < length; index += 1) {
|
|
246
|
+
if (!Object.is(first[index], second[index])) {
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
function differentValues(first, second) {
|
|
253
|
+
return Array.isArray(first) && Array.isArray(second)
|
|
254
|
+
? differentArrays(first, second)
|
|
255
|
+
: !Object.is(first, second);
|
|
256
|
+
}
|
|
257
|
+
function emitValue(state) {
|
|
258
|
+
for (const computed of state.computeds) {
|
|
259
|
+
computed.effect.dirty = true;
|
|
260
|
+
}
|
|
261
|
+
for (const effect of state.effects) {
|
|
262
|
+
batchedHandlers.add(effect);
|
|
263
|
+
}
|
|
264
|
+
for (const [, subscription] of state.subscriptions) {
|
|
265
|
+
batchedHandlers.add(subscription);
|
|
266
|
+
}
|
|
267
|
+
if (batchDepth === 0) {
|
|
268
|
+
flushHandlers();
|
|
269
|
+
}
|
|
270
|
+
}
|
|
267
271
|
function getValue(state) {
|
|
268
272
|
if (activeComputed != null) {
|
|
269
273
|
state.computeds.add(activeComputed);
|
|
@@ -273,12 +277,6 @@ function getValue(state) {
|
|
|
273
277
|
}
|
|
274
278
|
return state.value;
|
|
275
279
|
}
|
|
276
|
-
function setValue$1(state, value) {
|
|
277
|
-
if (!Object.is(state.value, value)) {
|
|
278
|
-
state.value = value;
|
|
279
|
-
emitValue(state);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
280
|
|
|
283
281
|
class Signal extends Reactive {
|
|
284
282
|
constructor(value) {
|
|
@@ -294,7 +292,10 @@ class Signal extends Reactive {
|
|
|
294
292
|
* Set the value
|
|
295
293
|
*/
|
|
296
294
|
set(value) {
|
|
297
|
-
|
|
295
|
+
if (differentValues(this.state.value, value)) {
|
|
296
|
+
this.state.value = value;
|
|
297
|
+
emitValue(this.state);
|
|
298
|
+
}
|
|
298
299
|
}
|
|
299
300
|
/**
|
|
300
301
|
* Update the value
|
|
@@ -343,6 +344,12 @@ class ReactiveArray extends Reactive {
|
|
|
343
344
|
at(index) {
|
|
344
345
|
return this.get().at(index);
|
|
345
346
|
}
|
|
347
|
+
/**
|
|
348
|
+
* Clear the array
|
|
349
|
+
*/
|
|
350
|
+
clear() {
|
|
351
|
+
this.length = 0;
|
|
352
|
+
}
|
|
346
353
|
/**
|
|
347
354
|
* @inheritdoc
|
|
348
355
|
*/
|
|
@@ -434,7 +441,7 @@ function updateArray(type, array, state, length) {
|
|
|
434
441
|
const result = array[type](...args);
|
|
435
442
|
if (affectsLength
|
|
436
443
|
? array.length !== previousLength
|
|
437
|
-
:
|
|
444
|
+
: differentArrays(previousArray, array)) {
|
|
438
445
|
emitValue(state);
|
|
439
446
|
length.set(array.length);
|
|
440
447
|
}
|
package/dist/value/array.cjs
CHANGED
|
@@ -7,7 +7,6 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
|
|
|
7
7
|
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
8
8
|
var _size;
|
|
9
9
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
10
|
-
const helpers_emit = require("../helpers/emit.cjs");
|
|
11
10
|
const helpers_is = require("../helpers/is.cjs");
|
|
12
11
|
const helpers_value = require("../helpers/value.cjs");
|
|
13
12
|
const value_computed = require("./computed.cjs");
|
|
@@ -45,6 +44,12 @@ class ReactiveArray extends value_reactive.Reactive {
|
|
|
45
44
|
at(index) {
|
|
46
45
|
return this.get().at(index);
|
|
47
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Clear the array
|
|
49
|
+
*/
|
|
50
|
+
clear() {
|
|
51
|
+
this.length = 0;
|
|
52
|
+
}
|
|
48
53
|
/**
|
|
49
54
|
* @inheritdoc
|
|
50
55
|
*/
|
|
@@ -123,7 +128,7 @@ function setValue(target, property, value, state, length) {
|
|
|
123
128
|
const previous = Reflect.get(target, property);
|
|
124
129
|
if (!Object.is(previous, value)) {
|
|
125
130
|
Reflect.set(target, property, value);
|
|
126
|
-
|
|
131
|
+
helpers_value.emitValue(state);
|
|
127
132
|
length.set(target.length);
|
|
128
133
|
}
|
|
129
134
|
return true;
|
|
@@ -136,8 +141,8 @@ function updateArray(type, array2, state, length) {
|
|
|
136
141
|
const result = array2[type](
|
|
137
142
|
...args
|
|
138
143
|
);
|
|
139
|
-
if (affectsLength ? array2.length !== previousLength :
|
|
140
|
-
|
|
144
|
+
if (affectsLength ? array2.length !== previousLength : helpers_value.differentArrays(previousArray, array2)) {
|
|
145
|
+
helpers_value.emitValue(state);
|
|
141
146
|
length.set(array2.length);
|
|
142
147
|
}
|
|
143
148
|
return result;
|
package/dist/value/array.js
CHANGED
|
@@ -5,9 +5,8 @@ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot
|
|
|
5
5
|
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
6
6
|
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
7
7
|
var _size;
|
|
8
|
-
import { emitValue, emitArrayChanges } from "../helpers/emit.js";
|
|
9
8
|
import { arrayName } from "../helpers/is.js";
|
|
10
|
-
import { getValue } from "../helpers/value.js";
|
|
9
|
+
import { getValue, emitValue, differentArrays } from "../helpers/value.js";
|
|
11
10
|
import { computed } from "./computed.js";
|
|
12
11
|
import { Reactive } from "./reactive.js";
|
|
13
12
|
import { signal } from "./signal.js";
|
|
@@ -43,6 +42,12 @@ class ReactiveArray extends Reactive {
|
|
|
43
42
|
at(index) {
|
|
44
43
|
return this.get().at(index);
|
|
45
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Clear the array
|
|
47
|
+
*/
|
|
48
|
+
clear() {
|
|
49
|
+
this.length = 0;
|
|
50
|
+
}
|
|
46
51
|
/**
|
|
47
52
|
* @inheritdoc
|
|
48
53
|
*/
|
|
@@ -134,7 +139,7 @@ function updateArray(type, array2, state, length) {
|
|
|
134
139
|
const result = array2[type](
|
|
135
140
|
...args
|
|
136
141
|
);
|
|
137
|
-
if (affectsLength ? array2.length !== previousLength :
|
|
142
|
+
if (affectsLength ? array2.length !== previousLength : differentArrays(previousArray, array2)) {
|
|
138
143
|
emitValue(state);
|
|
139
144
|
length.set(array2.length);
|
|
140
145
|
}
|
package/dist/value/computed.cjs
CHANGED
|
@@ -41,7 +41,7 @@ class Computed extends value_reactive.Reactive {
|
|
|
41
41
|
* @inheritdoc
|
|
42
42
|
*/
|
|
43
43
|
get() {
|
|
44
|
-
if (exports.activeComputed != null && exports.activeComputed
|
|
44
|
+
if (exports.activeComputed != null && this !== exports.activeComputed) {
|
|
45
45
|
this.state.computeds.add(exports.activeComputed);
|
|
46
46
|
}
|
|
47
47
|
if (effect.activeEffect != null && effect.activeEffect !== this.effect.instance) {
|
package/dist/value/computed.js
CHANGED
|
@@ -39,7 +39,7 @@ class Computed extends Reactive {
|
|
|
39
39
|
* @inheritdoc
|
|
40
40
|
*/
|
|
41
41
|
get() {
|
|
42
|
-
if (activeComputed != null &&
|
|
42
|
+
if (activeComputed != null && this !== activeComputed) {
|
|
43
43
|
this.state.computeds.add(activeComputed);
|
|
44
44
|
}
|
|
45
45
|
if (activeEffect != null && activeEffect !== this.effect.instance) {
|
package/dist/value/signal.cjs
CHANGED
|
@@ -17,7 +17,10 @@ class Signal extends value_reactive.Reactive {
|
|
|
17
17
|
* Set the value
|
|
18
18
|
*/
|
|
19
19
|
set(value) {
|
|
20
|
-
helpers_value.
|
|
20
|
+
if (helpers_value.differentValues(this.state.value, value)) {
|
|
21
|
+
this.state.value = value;
|
|
22
|
+
helpers_value.emitValue(this.state);
|
|
23
|
+
}
|
|
21
24
|
}
|
|
22
25
|
/**
|
|
23
26
|
* Update the value
|
package/dist/value/signal.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { signalName } from "../helpers/is.js";
|
|
2
|
-
import { getValue,
|
|
2
|
+
import { getValue, differentValues, emitValue } from "../helpers/value.js";
|
|
3
3
|
import { Reactive } from "./reactive.js";
|
|
4
4
|
class Signal extends Reactive {
|
|
5
5
|
constructor(value) {
|
|
@@ -15,7 +15,10 @@ class Signal extends Reactive {
|
|
|
15
15
|
* Set the value
|
|
16
16
|
*/
|
|
17
17
|
set(value) {
|
|
18
|
-
|
|
18
|
+
if (differentValues(this.state.value, value)) {
|
|
19
|
+
this.state.value = value;
|
|
20
|
+
emitValue(this.state);
|
|
21
|
+
}
|
|
19
22
|
}
|
|
20
23
|
/**
|
|
21
24
|
* Update the value
|
package/package.json
CHANGED
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
"@rollup/plugin-node-resolve": "^16",
|
|
13
13
|
"@rollup/plugin-typescript": "^12.1",
|
|
14
14
|
"@types/node": "^22.15",
|
|
15
|
-
"@vitest/coverage-istanbul": "^3.
|
|
15
|
+
"@vitest/coverage-istanbul": "^3.2",
|
|
16
16
|
"dts-bundle-generator": "^9.5",
|
|
17
17
|
"glob": "^11",
|
|
18
18
|
"jsdom": "^26.1",
|
|
19
19
|
"tslib": "^2.8",
|
|
20
20
|
"typescript": "^5.8",
|
|
21
21
|
"vite": "^6.3",
|
|
22
|
-
"vitest": "^3.
|
|
22
|
+
"vitest": "^3.2"
|
|
23
23
|
},
|
|
24
24
|
"exports": {
|
|
25
25
|
".": {
|
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
},
|
|
55
55
|
"type": "module",
|
|
56
56
|
"types": "./types/index.d.ts",
|
|
57
|
-
"version": "0.
|
|
57
|
+
"version": "0.16.0"
|
|
58
58
|
}
|
package/src/batch.ts
CHANGED
|
@@ -2,7 +2,7 @@ import {type Effect, runEffect} from './effect';
|
|
|
2
2
|
import {isEffect} from './helpers/is';
|
|
3
3
|
import type {Subscription} from './subscription';
|
|
4
4
|
|
|
5
|
-
export function
|
|
5
|
+
export function flushHandlers(): void {
|
|
6
6
|
while (batchDepth === 0 && batchedHandlers.size > 0) {
|
|
7
7
|
const handlers = [...batchedHandlers];
|
|
8
8
|
|
|
@@ -33,7 +33,7 @@ export function stopBatch(): void {
|
|
|
33
33
|
batchDepth -= 1;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
flushHandlers();
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export const batchedHandlers = new Set<Effect | Subscription<unknown>>();
|
package/src/helpers/is.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type {Effect} from '../effect';
|
|
|
3
3
|
import type {ReactiveArray} from '../value/array';
|
|
4
4
|
import type {Computed} from '../value/computed';
|
|
5
5
|
import type {Reactive} from '../value/reactive';
|
|
6
|
-
import
|
|
6
|
+
import type {Signal} from '../value/signal';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Is the value a reactive array?
|
package/src/helpers/value.ts
CHANGED
|
@@ -1,7 +1,62 @@
|
|
|
1
|
+
import {batchDepth, batchedHandlers, flushHandlers} from '../batch';
|
|
1
2
|
import {activeEffect} from '../effect';
|
|
2
|
-
import {activeComputed} from '../value/computed';
|
|
3
|
+
import {type InternalComputed, activeComputed} from '../value/computed';
|
|
3
4
|
import type {ReactiveState} from '../value/reactive';
|
|
4
|
-
|
|
5
|
+
|
|
6
|
+
export function differentArrays(first: unknown[], second: unknown[]): boolean {
|
|
7
|
+
let {length} = first;
|
|
8
|
+
|
|
9
|
+
if (length !== second.length) {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let offset = 0;
|
|
14
|
+
|
|
15
|
+
if (length >= 100) {
|
|
16
|
+
offset = Math.round(length / 10);
|
|
17
|
+
offset = offset > 25 ? 25 : offset;
|
|
18
|
+
|
|
19
|
+
for (let index = 0; index < offset; index += 1) {
|
|
20
|
+
if (!Object.is(first[index], second[index])) {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
length -= offset;
|
|
27
|
+
|
|
28
|
+
for (let index = offset; index < length; index += 1) {
|
|
29
|
+
if (!Object.is(first[index], second[index])) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function differentValues(first: unknown, second: unknown): boolean {
|
|
38
|
+
return Array.isArray(first) && Array.isArray(second)
|
|
39
|
+
? differentArrays(first, second)
|
|
40
|
+
: !Object.is(first, second);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function emitValue<Value>(state: ReactiveState<Value>): void {
|
|
44
|
+
for (const computed of state.computeds) {
|
|
45
|
+
(computed as unknown as InternalComputed).effect.dirty = true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
for (const effect of state.effects) {
|
|
49
|
+
batchedHandlers.add(effect);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
for (const [, subscription] of state.subscriptions) {
|
|
53
|
+
batchedHandlers.add(subscription as never);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (batchDepth === 0) {
|
|
57
|
+
flushHandlers();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
5
60
|
|
|
6
61
|
export function getValue<Value>(state: ReactiveState<Value>): Value {
|
|
7
62
|
if (activeComputed != null) {
|
|
@@ -14,14 +69,3 @@ export function getValue<Value>(state: ReactiveState<Value>): Value {
|
|
|
14
69
|
|
|
15
70
|
return state.value;
|
|
16
71
|
}
|
|
17
|
-
|
|
18
|
-
export function setValue<Value>(
|
|
19
|
-
state: ReactiveState<Value>,
|
|
20
|
-
value: Value,
|
|
21
|
-
): void {
|
|
22
|
-
if (!Object.is(state.value, value)) {
|
|
23
|
-
state.value = value;
|
|
24
|
-
|
|
25
|
-
emitValue(state);
|
|
26
|
-
}
|
|
27
|
-
}
|
package/src/value/array.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {emitArrayChanges, emitValue} from '../helpers/emit';
|
|
2
1
|
import {arrayName} from '../helpers/is';
|
|
3
|
-
import {getValue} from '../helpers/value';
|
|
2
|
+
import {differentArrays, emitValue, getValue} from '../helpers/value';
|
|
4
3
|
import {type Computed, computed} from './computed';
|
|
5
4
|
import {Reactive, type ReactiveState} from './reactive';
|
|
6
5
|
import {type Signal, signal} from './signal';
|
|
@@ -51,6 +50,13 @@ export class ReactiveArray<Item> extends Reactive<Item[]> {
|
|
|
51
50
|
return this.get().at(index);
|
|
52
51
|
}
|
|
53
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Clear the array
|
|
55
|
+
*/
|
|
56
|
+
clear(): void {
|
|
57
|
+
this.length = 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
54
60
|
/**
|
|
55
61
|
* @inheritdoc
|
|
56
62
|
*/
|
|
@@ -207,7 +213,7 @@ function updateArray<Item>(
|
|
|
207
213
|
if (
|
|
208
214
|
affectsLength
|
|
209
215
|
? array.length !== previousLength
|
|
210
|
-
:
|
|
216
|
+
: differentArrays(previousArray, array)
|
|
211
217
|
) {
|
|
212
218
|
emitValue(state);
|
|
213
219
|
|
package/src/value/computed.ts
CHANGED
|
@@ -3,7 +3,7 @@ import {type Effect, activeEffect, effect, runEffect} from '../effect';
|
|
|
3
3
|
import {computedName} from '../helpers/is';
|
|
4
4
|
import {Reactive, type ReactiveState} from './reactive';
|
|
5
5
|
|
|
6
|
-
type ComputedEffect = {
|
|
6
|
+
export type ComputedEffect = {
|
|
7
7
|
dirty: boolean;
|
|
8
8
|
instance: Effect;
|
|
9
9
|
};
|
|
@@ -59,7 +59,7 @@ export class Computed<Value> extends Reactive<Value> {
|
|
|
59
59
|
* @inheritdoc
|
|
60
60
|
*/
|
|
61
61
|
get(): Value {
|
|
62
|
-
if (activeComputed != null &&
|
|
62
|
+
if (activeComputed != null && this !== activeComputed) {
|
|
63
63
|
this.state.computeds.add(activeComputed);
|
|
64
64
|
}
|
|
65
65
|
|
package/src/value/signal.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {signalName} from '../helpers/is';
|
|
2
|
-
import {
|
|
2
|
+
import {differentValues, emitValue, getValue} from '../helpers/value';
|
|
3
3
|
import {Reactive} from './reactive';
|
|
4
4
|
|
|
5
5
|
export class Signal<Value> extends Reactive<Value> {
|
|
@@ -18,7 +18,11 @@ export class Signal<Value> extends Reactive<Value> {
|
|
|
18
18
|
* Set the value
|
|
19
19
|
*/
|
|
20
20
|
set(value: Value): void {
|
|
21
|
-
|
|
21
|
+
if (differentValues(this.state.value, value)) {
|
|
22
|
+
this.state.value = value;
|
|
23
|
+
|
|
24
|
+
emitValue(this.state);
|
|
25
|
+
}
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
/**
|
package/types/batch.d.cts
CHANGED
|
@@ -57,7 +57,7 @@ declare class Subscription<Value> {
|
|
|
57
57
|
* Unsubscribe from changes
|
|
58
58
|
*/
|
|
59
59
|
export type Unsubscribe = () => void;
|
|
60
|
-
export declare function
|
|
60
|
+
export declare function flushHandlers(): void;
|
|
61
61
|
/**
|
|
62
62
|
* Start batching effects _(use `stopBatch` to flush and run batched effects)_
|
|
63
63
|
*/
|
package/types/batch.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Effect } from './effect';
|
|
2
2
|
import type { Subscription } from './subscription';
|
|
3
|
-
export declare function
|
|
3
|
+
export declare function flushHandlers(): void;
|
|
4
4
|
/**
|
|
5
5
|
* Start batching effects _(use `stopBatch` to flush and run batched effects)_
|
|
6
6
|
*/
|
package/types/helpers/is.d.cts
CHANGED
package/types/helpers/is.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { Effect } from '../effect';
|
|
|
2
2
|
import type { ReactiveArray } from '../value/array';
|
|
3
3
|
import type { Computed } from '../value/computed';
|
|
4
4
|
import type { Reactive } from '../value/reactive';
|
|
5
|
-
import {
|
|
5
|
+
import type { Signal } from '../value/signal';
|
|
6
6
|
/**
|
|
7
7
|
* Is the value a reactive array?
|
|
8
8
|
*/
|
|
@@ -57,7 +57,9 @@ declare class Subscription<Value> {
|
|
|
57
57
|
* Unsubscribe from changes
|
|
58
58
|
*/
|
|
59
59
|
export type Unsubscribe = () => void;
|
|
60
|
+
export declare function differentArrays(first: unknown[], second: unknown[]): boolean;
|
|
61
|
+
export declare function differentValues(first: unknown, second: unknown): boolean;
|
|
62
|
+
export declare function emitValue<Value>(state: ReactiveState<Value>): void;
|
|
60
63
|
export declare function getValue<Value>(state: ReactiveState<Value>): Value;
|
|
61
|
-
export declare function setValue<Value>(state: ReactiveState<Value>, value: Value): void;
|
|
62
64
|
|
|
63
65
|
export {};
|
package/types/helpers/value.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { ReactiveState } from '../value/reactive';
|
|
2
|
+
export declare function differentArrays(first: unknown[], second: unknown[]): boolean;
|
|
3
|
+
export declare function differentValues(first: unknown, second: unknown): boolean;
|
|
4
|
+
export declare function emitValue<Value>(state: ReactiveState<Value>): void;
|
|
2
5
|
export declare function getValue<Value>(state: ReactiveState<Value>): Value;
|
|
3
|
-
export declare function setValue<Value>(state: ReactiveState<Value>, value: Value): void;
|
package/types/index.d.cts
CHANGED
package/types/value/array.d.cts
CHANGED
package/types/value/array.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Effect } from '../effect';
|
|
2
2
|
import { Reactive, type ReactiveState } from './reactive';
|
|
3
|
-
type ComputedEffect = {
|
|
3
|
+
export type ComputedEffect = {
|
|
4
4
|
dirty: boolean;
|
|
5
5
|
instance: Effect;
|
|
6
6
|
};
|
|
@@ -21,4 +21,3 @@ export declare class Computed<Value> extends Reactive<Value> {
|
|
|
21
21
|
* Create a computed value
|
|
22
22
|
*/
|
|
23
23
|
export declare function computed<Value>(callback: () => Value): Computed<Value>;
|
|
24
|
-
export {};
|
package/dist/helpers/emit.cjs
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const batch = require("../batch.cjs");
|
|
4
|
-
function emitArrayChanges(first, second) {
|
|
5
|
-
let { length } = first;
|
|
6
|
-
if (length !== second.length) {
|
|
7
|
-
return true;
|
|
8
|
-
}
|
|
9
|
-
let offset = 0;
|
|
10
|
-
if (length >= 100) {
|
|
11
|
-
offset = Math.round(length / 10);
|
|
12
|
-
offset = offset > 25 ? 25 : offset;
|
|
13
|
-
for (let index = 0; index < offset; index += 1) {
|
|
14
|
-
if (!Object.is(first[index], second[index])) {
|
|
15
|
-
return true;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
length -= offset;
|
|
20
|
-
for (let index = offset; index < length; index += 1) {
|
|
21
|
-
if (!Object.is(first[index], second[index])) {
|
|
22
|
-
return true;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
return false;
|
|
26
|
-
}
|
|
27
|
-
function emitValue(state) {
|
|
28
|
-
for (const computed of state.computeds) {
|
|
29
|
-
computed.effect.dirty = true;
|
|
30
|
-
}
|
|
31
|
-
for (const effect of state.effects) {
|
|
32
|
-
batch.batchedHandlers.add(effect);
|
|
33
|
-
}
|
|
34
|
-
for (const [, subscription] of state.subscriptions) {
|
|
35
|
-
batch.batchedHandlers.add(subscription);
|
|
36
|
-
}
|
|
37
|
-
if (batch.batchDepth === 0) {
|
|
38
|
-
batch.flushEffects();
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
exports.emitArrayChanges = emitArrayChanges;
|
|
42
|
-
exports.emitValue = emitValue;
|
package/dist/helpers/emit.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { batchedHandlers, batchDepth, flushEffects } from "../batch.js";
|
|
2
|
-
function emitArrayChanges(first, second) {
|
|
3
|
-
let { length } = first;
|
|
4
|
-
if (length !== second.length) {
|
|
5
|
-
return true;
|
|
6
|
-
}
|
|
7
|
-
let offset = 0;
|
|
8
|
-
if (length >= 100) {
|
|
9
|
-
offset = Math.round(length / 10);
|
|
10
|
-
offset = offset > 25 ? 25 : offset;
|
|
11
|
-
for (let index = 0; index < offset; index += 1) {
|
|
12
|
-
if (!Object.is(first[index], second[index])) {
|
|
13
|
-
return true;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
length -= offset;
|
|
18
|
-
for (let index = offset; index < length; index += 1) {
|
|
19
|
-
if (!Object.is(first[index], second[index])) {
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
function emitValue(state) {
|
|
26
|
-
for (const computed of state.computeds) {
|
|
27
|
-
computed.effect.dirty = true;
|
|
28
|
-
}
|
|
29
|
-
for (const effect of state.effects) {
|
|
30
|
-
batchedHandlers.add(effect);
|
|
31
|
-
}
|
|
32
|
-
for (const [, subscription] of state.subscriptions) {
|
|
33
|
-
batchedHandlers.add(subscription);
|
|
34
|
-
}
|
|
35
|
-
if (batchDepth === 0) {
|
|
36
|
-
flushEffects();
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
export {
|
|
40
|
-
emitArrayChanges,
|
|
41
|
-
emitValue
|
|
42
|
-
};
|
package/src/helpers/emit.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import {batchDepth, batchedHandlers, flushEffects} from '../batch';
|
|
2
|
-
import type {InternalComputed} from '../value/computed';
|
|
3
|
-
import type {ReactiveState} from '../value/reactive';
|
|
4
|
-
|
|
5
|
-
export function emitArrayChanges(first: unknown[], second: unknown[]): boolean {
|
|
6
|
-
let {length} = first;
|
|
7
|
-
|
|
8
|
-
if (length !== second.length) {
|
|
9
|
-
return true;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
let offset = 0;
|
|
13
|
-
|
|
14
|
-
if (length >= 100) {
|
|
15
|
-
offset = Math.round(length / 10);
|
|
16
|
-
offset = offset > 25 ? 25 : offset;
|
|
17
|
-
|
|
18
|
-
for (let index = 0; index < offset; index += 1) {
|
|
19
|
-
if (!Object.is(first[index], second[index])) {
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
length -= offset;
|
|
26
|
-
|
|
27
|
-
for (let index = offset; index < length; index += 1) {
|
|
28
|
-
if (!Object.is(first[index], second[index])) {
|
|
29
|
-
return true;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function emitValue<Value>(state: ReactiveState<Value>): void {
|
|
37
|
-
for (const computed of state.computeds) {
|
|
38
|
-
(computed as unknown as InternalComputed).effect.dirty = true;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
for (const effect of state.effects) {
|
|
42
|
-
batchedHandlers.add(effect);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
for (const [, subscription] of state.subscriptions) {
|
|
46
|
-
batchedHandlers.add(subscription as never);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (batchDepth === 0) {
|
|
50
|
-
flushEffects();
|
|
51
|
-
}
|
|
52
|
-
}
|
package/types/helpers/emit.d.cts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
// Generated by dts-bundle-generator v9.5.1
|
|
2
|
-
|
|
3
|
-
export type GenericCallback = (...args: any[]) => any;
|
|
4
|
-
declare class Effect {
|
|
5
|
-
private readonly $mora;
|
|
6
|
-
private readonly state;
|
|
7
|
-
constructor(callback: GenericCallback);
|
|
8
|
-
}
|
|
9
|
-
declare class Computed<Value> extends Reactive<Value> {
|
|
10
|
-
private readonly effect;
|
|
11
|
-
constructor(callback: () => Value);
|
|
12
|
-
/**
|
|
13
|
-
* @inheritdoc
|
|
14
|
-
*/
|
|
15
|
-
get(): Value;
|
|
16
|
-
}
|
|
17
|
-
declare abstract class Reactive<Value> {
|
|
18
|
-
protected readonly state: ReactiveState<Value>;
|
|
19
|
-
constructor(name: string, value: Value);
|
|
20
|
-
/**
|
|
21
|
-
* Get the value
|
|
22
|
-
*/
|
|
23
|
-
abstract get(): Value;
|
|
24
|
-
/**
|
|
25
|
-
* Get the value _(without reactivity)_
|
|
26
|
-
*/
|
|
27
|
-
peek(): Value;
|
|
28
|
-
/**
|
|
29
|
-
* Subscribe to changes
|
|
30
|
-
*/
|
|
31
|
-
subscribe(callback: (value: Value) => void): Unsubscribe;
|
|
32
|
-
/**
|
|
33
|
-
* JSON representation of the value
|
|
34
|
-
*/
|
|
35
|
-
toJSON(): Value;
|
|
36
|
-
/**
|
|
37
|
-
* String representation of the value
|
|
38
|
-
*/
|
|
39
|
-
toString(): string;
|
|
40
|
-
/**
|
|
41
|
-
* Unsubscribe from changes
|
|
42
|
-
*/
|
|
43
|
-
unsubscribe(callback: (value: Value) => void): void;
|
|
44
|
-
}
|
|
45
|
-
export type ReactiveState<Value> = {
|
|
46
|
-
computeds: Set<Computed<unknown>>;
|
|
47
|
-
effects: Set<Effect>;
|
|
48
|
-
subscriptions: Map<(value: Value) => void, Subscription<Value>>;
|
|
49
|
-
value: Value;
|
|
50
|
-
};
|
|
51
|
-
declare class Subscription<Value> {
|
|
52
|
-
state: ReactiveState<Value>;
|
|
53
|
-
callback: GenericCallback;
|
|
54
|
-
constructor(state: ReactiveState<Value>, callback: GenericCallback);
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Unsubscribe from changes
|
|
58
|
-
*/
|
|
59
|
-
export type Unsubscribe = () => void;
|
|
60
|
-
export declare function emitArrayChanges(first: unknown[], second: unknown[]): boolean;
|
|
61
|
-
export declare function emitValue<Value>(state: ReactiveState<Value>): void;
|
|
62
|
-
|
|
63
|
-
export {};
|
package/types/helpers/emit.d.ts
DELETED