@oscarpalmer/mora 0.12.0 → 0.14.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.
Files changed (59) hide show
  1. package/dist/batch.cjs +2 -2
  2. package/dist/batch.js +1 -1
  3. package/dist/effect.cjs +2 -1
  4. package/dist/effect.js +2 -1
  5. package/dist/helpers/emit.cjs +42 -0
  6. package/dist/helpers/emit.js +42 -0
  7. package/dist/helpers/is.cjs +34 -0
  8. package/dist/helpers/is.js +34 -0
  9. package/dist/helpers/value.cjs +22 -0
  10. package/dist/helpers/value.js +22 -0
  11. package/dist/index.cjs +12 -9
  12. package/dist/index.js +6 -3
  13. package/dist/mora.full.js +214 -55
  14. package/dist/value/array.cjs +108 -0
  15. package/dist/value/array.js +108 -0
  16. package/dist/{computed.cjs → value/computed.cjs} +6 -5
  17. package/dist/{computed.js → value/computed.js} +4 -3
  18. package/dist/{reactive.cjs → value/reactive.cjs} +13 -1
  19. package/dist/{reactive.js → value/reactive.js} +13 -1
  20. package/dist/value/signal.cjs +33 -0
  21. package/dist/value/signal.js +33 -0
  22. package/package.json +1 -1
  23. package/src/batch.ts +1 -1
  24. package/src/effect.ts +12 -11
  25. package/src/helpers/emit.ts +52 -0
  26. package/src/helpers/is.ts +56 -0
  27. package/src/helpers/value.ts +27 -0
  28. package/src/index.ts +11 -5
  29. package/src/subscription.ts +1 -1
  30. package/src/value/array.ts +170 -0
  31. package/src/{computed.ts → value/computed.ts} +4 -3
  32. package/src/{reactive.ts → value/reactive.ts} +17 -3
  33. package/src/value/signal.ts +37 -0
  34. package/types/batch.d.cts +8 -0
  35. package/types/{is.d.cts → helpers/emit.d.cts} +10 -28
  36. package/types/helpers/emit.d.ts +3 -0
  37. package/types/helpers/is.d.cts +133 -0
  38. package/types/helpers/is.d.ts +26 -0
  39. package/types/helpers/value.d.cts +63 -0
  40. package/types/helpers/value.d.ts +3 -0
  41. package/types/index.d.cts +63 -8
  42. package/types/index.d.ts +5 -4
  43. package/types/subscription.d.cts +8 -0
  44. package/types/subscription.d.ts +1 -1
  45. package/types/value/array.d.cts +101 -0
  46. package/types/value/array.d.ts +41 -0
  47. package/types/{computed.d.cts → value/computed.d.cts} +8 -0
  48. package/types/{computed.d.ts → value/computed.d.ts} +1 -1
  49. package/types/{reactive.d.cts → value/reactive.d.cts} +8 -0
  50. package/types/{reactive.d.ts → value/reactive.d.ts} +10 -2
  51. package/types/{signal.d.cts → value/signal.d.cts} +11 -0
  52. package/types/{signal.d.ts → value/signal.d.ts} +3 -0
  53. package/dist/is.cjs +0 -21
  54. package/dist/is.js +0 -21
  55. package/dist/signal.cjs +0 -55
  56. package/dist/signal.js +0 -55
  57. package/src/is.ts +0 -39
  58. package/src/signal.ts +0 -63
  59. package/types/is.d.ts +0 -17
package/dist/batch.cjs CHANGED
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const effect = require("./effect.cjs");
4
- const is = require("./is.cjs");
4
+ const helpers_is = require("./helpers/is.cjs");
5
5
  function flushEffects() {
6
6
  while (exports.batchDepth === 0 && batchedHandlers.size > 0) {
7
7
  const handlers = [...batchedHandlers];
8
8
  batchedHandlers.clear();
9
9
  for (const handler of handlers) {
10
- if (is.isEffect(handler)) {
10
+ if (helpers_is.isEffect(handler)) {
11
11
  effect.runEffect(handler);
12
12
  } else {
13
13
  handler.callback(handler.state.value);
package/dist/batch.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { runEffect } from "./effect.js";
2
- import { isEffect } from "./is.js";
2
+ import { isEffect } from "./helpers/is.js";
3
3
  function flushEffects() {
4
4
  while (batchDepth === 0 && batchedHandlers.size > 0) {
5
5
  const handlers = [...batchedHandlers];
package/dist/effect.cjs CHANGED
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const helpers_is = require("./helpers/is.cjs");
3
4
  class Effect {
4
5
  constructor(callback) {
5
6
  Object.defineProperty(this, "$mora", {
6
- value: "effect"
7
+ value: helpers_is.effectName
7
8
  });
8
9
  this.state = {
9
10
  callback
package/dist/effect.js CHANGED
@@ -1,7 +1,8 @@
1
+ import { effectName } from "./helpers/is.js";
1
2
  class Effect {
2
3
  constructor(callback) {
3
4
  Object.defineProperty(this, "$mora", {
4
- value: "effect"
5
+ value: effectName
5
6
  });
6
7
  this.state = {
7
8
  callback
@@ -0,0 +1,42 @@
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;
@@ -0,0 +1,42 @@
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
+ };
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ function isArray(value) {
4
+ return isMora(value, arrayName);
5
+ }
6
+ function isComputed(value) {
7
+ return isMora(value, computedName);
8
+ }
9
+ function isEffect(value) {
10
+ return isMora(value, effectName);
11
+ }
12
+ function isMora(value, name) {
13
+ return typeof value === "object" && value != null && "$mora" in value && (typeof name === "string" ? value.$mora === name : name.has(value.$mora));
14
+ }
15
+ function isReactive(value) {
16
+ return isMora(value, reactiveNames);
17
+ }
18
+ function isSignal(value) {
19
+ return isMora(value, signalName);
20
+ }
21
+ const arrayName = "array";
22
+ const computedName = "computed";
23
+ const effectName = "effect";
24
+ const signalName = "signal";
25
+ const reactiveNames = /* @__PURE__ */ new Set([arrayName, computedName, signalName]);
26
+ exports.arrayName = arrayName;
27
+ exports.computedName = computedName;
28
+ exports.effectName = effectName;
29
+ exports.isArray = isArray;
30
+ exports.isComputed = isComputed;
31
+ exports.isEffect = isEffect;
32
+ exports.isReactive = isReactive;
33
+ exports.isSignal = isSignal;
34
+ exports.signalName = signalName;
@@ -0,0 +1,34 @@
1
+ function isArray(value) {
2
+ return isMora(value, arrayName);
3
+ }
4
+ function isComputed(value) {
5
+ return isMora(value, computedName);
6
+ }
7
+ function isEffect(value) {
8
+ return isMora(value, effectName);
9
+ }
10
+ function isMora(value, name) {
11
+ return typeof value === "object" && value != null && "$mora" in value && (typeof name === "string" ? value.$mora === name : name.has(value.$mora));
12
+ }
13
+ function isReactive(value) {
14
+ return isMora(value, reactiveNames);
15
+ }
16
+ function isSignal(value) {
17
+ return isMora(value, signalName);
18
+ }
19
+ const arrayName = "array";
20
+ const computedName = "computed";
21
+ const effectName = "effect";
22
+ const signalName = "signal";
23
+ const reactiveNames = /* @__PURE__ */ new Set([arrayName, computedName, signalName]);
24
+ export {
25
+ arrayName,
26
+ computedName,
27
+ effectName,
28
+ isArray,
29
+ isComputed,
30
+ isEffect,
31
+ isReactive,
32
+ isSignal,
33
+ signalName
34
+ };
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const effect = require("../effect.cjs");
4
+ const value_computed = require("../value/computed.cjs");
5
+ const helpers_emit = require("./emit.cjs");
6
+ function getValue(state) {
7
+ if (value_computed.activeComputed != null) {
8
+ state.computeds.add(value_computed.activeComputed);
9
+ }
10
+ if (effect.activeEffect != null) {
11
+ state.effects.add(effect.activeEffect);
12
+ }
13
+ return state.value;
14
+ }
15
+ function setValue(state, value) {
16
+ if (!Object.is(state.value, value)) {
17
+ state.value = value;
18
+ helpers_emit.emitValue(state);
19
+ }
20
+ }
21
+ exports.getValue = getValue;
22
+ exports.setValue = setValue;
@@ -0,0 +1,22 @@
1
+ import { activeEffect } from "../effect.js";
2
+ import { activeComputed } from "../value/computed.js";
3
+ import { emitValue } from "./emit.js";
4
+ function getValue(state) {
5
+ if (activeComputed != null) {
6
+ state.computeds.add(activeComputed);
7
+ }
8
+ if (activeEffect != null) {
9
+ state.effects.add(activeEffect);
10
+ }
11
+ return state.value;
12
+ }
13
+ function setValue(state, value) {
14
+ if (!Object.is(state.value, value)) {
15
+ state.value = value;
16
+ emitValue(state);
17
+ }
18
+ }
19
+ export {
20
+ getValue,
21
+ setValue
22
+ };
package/dist/index.cjs CHANGED
@@ -1,16 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const batch = require("./batch.cjs");
4
- const computed = require("./computed.cjs");
5
4
  const effect = require("./effect.cjs");
6
- const is = require("./is.cjs");
7
- const signal = require("./signal.cjs");
5
+ const helpers_is = require("./helpers/is.cjs");
6
+ const value_array = require("./value/array.cjs");
7
+ const value_computed = require("./value/computed.cjs");
8
+ const value_signal = require("./value/signal.cjs");
8
9
  exports.startBatch = batch.startBatch;
9
10
  exports.stopBatch = batch.stopBatch;
10
- exports.computed = computed.computed;
11
11
  exports.effect = effect.effect;
12
- exports.isComputed = is.isComputed;
13
- exports.isEffect = is.isEffect;
14
- exports.isReactive = is.isReactive;
15
- exports.isSignal = is.isSignal;
16
- exports.signal = signal.signal;
12
+ exports.isArray = helpers_is.isArray;
13
+ exports.isComputed = helpers_is.isComputed;
14
+ exports.isEffect = helpers_is.isEffect;
15
+ exports.isReactive = helpers_is.isReactive;
16
+ exports.isSignal = helpers_is.isSignal;
17
+ exports.array = value_array.array;
18
+ exports.computed = value_computed.computed;
19
+ exports.signal = value_signal.signal;
package/dist/index.js CHANGED
@@ -1,11 +1,14 @@
1
1
  import { startBatch, stopBatch } from "./batch.js";
2
- import { computed } from "./computed.js";
3
2
  import { effect } from "./effect.js";
4
- import { isComputed, isEffect, isReactive, isSignal } from "./is.js";
5
- import { signal } from "./signal.js";
3
+ import { isArray, isComputed, isEffect, isReactive, isSignal } from "./helpers/is.js";
4
+ import { array } from "./value/array.js";
5
+ import { computed } from "./value/computed.js";
6
+ import { signal } from "./value/signal.js";
6
7
  export {
8
+ array,
7
9
  computed,
8
10
  effect,
11
+ isArray,
9
12
  isComputed,
10
13
  isEffect,
11
14
  isReactive,
package/dist/mora.full.js CHANGED
@@ -1,7 +1,48 @@
1
+ /**
2
+ * Is the value a reactive array?
3
+ */
4
+ function isArray(value) {
5
+ return isMora(value, arrayName);
6
+ }
7
+ /**
8
+ * Is the value a computed signal?
9
+ */
10
+ function isComputed(value) {
11
+ return isMora(value, computedName);
12
+ }
13
+ /**
14
+ * Is the value an effect?
15
+ */
16
+ function isEffect(value) {
17
+ return isMora(value, effectName);
18
+ }
19
+ function isMora(value, name) {
20
+ return (typeof value === 'object' &&
21
+ value != null &&
22
+ '$mora' in value &&
23
+ (typeof name === 'string'
24
+ ? value.$mora === name
25
+ : name.has(value.$mora)));
26
+ }
27
+ function isReactive(value) {
28
+ return isMora(value, reactiveNames);
29
+ }
30
+ /**
31
+ * Is the value a signal?
32
+ */
33
+ function isSignal(value) {
34
+ return isMora(value, signalName);
35
+ }
36
+ const arrayName = 'array';
37
+ const computedName = 'computed';
38
+ const effectName = 'effect';
39
+ const signalName = 'signal';
40
+ const reactiveNames = new Set([arrayName, computedName, signalName]);
41
+
1
42
  class Effect {
2
43
  constructor(callback) {
3
44
  Object.defineProperty(this, '$mora', {
4
- value: 'effect',
45
+ value: effectName,
5
46
  });
6
47
  this.state = {
7
48
  callback,
@@ -27,34 +68,6 @@ function effect(callback) {
27
68
  }
28
69
  let activeEffect;
29
70
 
30
- /**
31
- * Is the value a computed signal?
32
- */
33
- function isComputed(value) {
34
- return isMora(value, 'computed');
35
- }
36
- /**
37
- * Is the value an effect?
38
- */
39
- function isEffect(value) {
40
- return isMora(value, 'effect');
41
- }
42
- function isMora(value, name) {
43
- return (typeof value === 'object' &&
44
- value != null &&
45
- '$mora' in value &&
46
- value.$mora === name);
47
- }
48
- function isReactive(value) {
49
- return isComputed(value) || isSignal(value);
50
- }
51
- /**
52
- * Is the value a signal?
53
- */
54
- function isSignal(value) {
55
- return isMora(value, 'signal');
56
- }
57
-
58
71
  function flushEffects() {
59
72
  while (batchDepth === 0 && batchedHandlers.size > 0) {
60
73
  const handlers = [...batchedHandlers];
@@ -87,6 +100,44 @@ function stopBatch() {
87
100
  const batchedHandlers = new Set();
88
101
  let batchDepth = 0;
89
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
+
90
141
  class Subscription {
91
142
  state;
92
143
  callback;
@@ -140,6 +191,18 @@ class Reactive {
140
191
  subscribe(callback) {
141
192
  return subscribe(this.state, callback);
142
193
  }
194
+ /**
195
+ * JSON representation of the value
196
+ */
197
+ toJSON() {
198
+ return this.get();
199
+ }
200
+ /**
201
+ * String representation of the value
202
+ */
203
+ toString() {
204
+ return String(this.get());
205
+ }
143
206
  /**
144
207
  * Unsubscribe from changes
145
208
  */
@@ -155,7 +218,7 @@ class Computed extends Reactive {
155
218
  instance: undefined,
156
219
  };
157
220
  constructor(callback) {
158
- super('computed', undefined);
221
+ super(computedName, undefined);
159
222
  this.effect.instance = effect(() => {
160
223
  if (this.effect.dirty) {
161
224
  const previousComputed = activeComputed;
@@ -201,42 +264,37 @@ function computed(callback) {
201
264
  return new Computed(callback);
202
265
  }
203
266
 
267
+ function getValue(state) {
268
+ if (activeComputed != null) {
269
+ state.computeds.add(activeComputed);
270
+ }
271
+ if (activeEffect != null) {
272
+ state.effects.add(activeEffect);
273
+ }
274
+ return state.value;
275
+ }
276
+ function setValue$1(state, value) {
277
+ if (!Object.is(state.value, value)) {
278
+ state.value = value;
279
+ emitValue(state);
280
+ }
281
+ }
282
+
204
283
  class Signal extends Reactive {
205
284
  constructor(value) {
206
- super('signal', value);
285
+ super(signalName, value);
207
286
  }
208
287
  /**
209
288
  * @inheritdoc
210
289
  */
211
290
  get() {
212
- if (activeComputed != null) {
213
- this.state.computeds.add(activeComputed);
214
- }
215
- if (activeEffect != null) {
216
- this.state.effects.add(activeEffect);
217
- }
218
- return this.state.value;
291
+ return getValue(this.state);
219
292
  }
220
293
  /**
221
294
  * Set the value
222
295
  */
223
296
  set(value) {
224
- if (Object.is(this.state.value, value)) {
225
- return;
226
- }
227
- this.state.value = value;
228
- for (const computed of this.state.computeds) {
229
- computed.effect.dirty = true;
230
- }
231
- for (const effect of this.state.effects) {
232
- batchedHandlers.add(effect);
233
- }
234
- for (const [, subscription] of this.state.subscriptions) {
235
- batchedHandlers.add(subscription);
236
- }
237
- if (batchDepth === 0) {
238
- flushEffects();
239
- }
297
+ setValue$1(this.state, value);
240
298
  }
241
299
  /**
242
300
  * Update the value
@@ -245,8 +303,109 @@ class Signal extends Reactive {
245
303
  this.set(callback(this.state.value));
246
304
  }
247
305
  }
306
+ /**
307
+ * Create a reactive value
308
+ */
248
309
  function signal(value) {
249
310
  return new Signal(value);
250
311
  }
251
312
 
252
- export { computed, effect, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch };
313
+ class ReactiveArray extends Reactive {
314
+ #size = signal(0);
315
+ /**
316
+ * The length of the array
317
+ */
318
+ get length() {
319
+ return this.#size.get();
320
+ }
321
+ /**
322
+ * Set the length of the array
323
+ */
324
+ set length(value) {
325
+ if (typeof value === 'number' &&
326
+ value >= 0 &&
327
+ value !== this.state.value.length) {
328
+ this.get().length = value;
329
+ }
330
+ }
331
+ constructor(value) {
332
+ super(arrayName, new Proxy(value, {
333
+ get: (target, property) => updateMethods.has(property)
334
+ ? updateArray(property, target, this.state, this.#size)
335
+ : Reflect.get(target, property),
336
+ set: (target, property, value) => setValue(target, property, value, this.state, this.#size),
337
+ }));
338
+ this.#size.set(value.length);
339
+ }
340
+ /**
341
+ * @inheritdoc
342
+ */
343
+ get() {
344
+ return getValue(this.state);
345
+ }
346
+ peek(length) {
347
+ return length === true ? this.#size.peek() : [...this.state.value];
348
+ }
349
+ set(first, second) {
350
+ if (Array.isArray(first)) {
351
+ this.state.value.splice(0, this.state.value.length, ...first);
352
+ }
353
+ else if (first === 'length') {
354
+ this.length = second;
355
+ }
356
+ else if (typeof first === 'number') {
357
+ this.state.value[first] = second;
358
+ }
359
+ }
360
+ }
361
+ /**
362
+ * Create a reactive array
363
+ */
364
+ function array(value) {
365
+ return new ReactiveArray(Array.isArray(value) ? value : []);
366
+ }
367
+ function setValue(target, property, value, state, length) {
368
+ const isIndex = !Number.isNaN(Number(property));
369
+ const isLength = property === 'length';
370
+ if (!isIndex && !isLength) {
371
+ return Reflect.set(target, property, value);
372
+ }
373
+ const previous = Reflect.get(target, property);
374
+ if (!Object.is(previous, value)) {
375
+ Reflect.set(target, property, value);
376
+ emitValue(state);
377
+ length.set(target.length);
378
+ }
379
+ return true;
380
+ }
381
+ function updateArray(type, array, state, length) {
382
+ const affectsLength = lengthAffectingMethods.has(type);
383
+ const previousArray = affectsLength ? [] : [...array];
384
+ const previousLength = array.length;
385
+ return (...args) => {
386
+ const result = array[type](...args);
387
+ if (affectsLength
388
+ ? array.length !== previousLength
389
+ : emitArrayChanges(previousArray, array)) {
390
+ emitValue(state);
391
+ length.set(array.length);
392
+ }
393
+ return result;
394
+ };
395
+ }
396
+ const lengthAffectingMethods = new Set([
397
+ 'pop',
398
+ 'push',
399
+ 'shift',
400
+ 'unshift',
401
+ ]);
402
+ const updateMethods = new Set([
403
+ ...lengthAffectingMethods,
404
+ 'copyWithin',
405
+ 'fill',
406
+ 'reverse',
407
+ 'sort',
408
+ 'splice',
409
+ ]);
410
+
411
+ export { array, computed, effect, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch };