@esportsplus/reactivity 0.31.3 → 0.33.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 (67) hide show
  1. package/README.md +43 -6
  2. package/bench/cellx.bench.ts +61 -0
  3. package/bench/dynamic.bench.ts +103 -0
  4. package/bench/kairo.bench.ts +368 -0
  5. package/bench/lib/reactive-adapter.ts +51 -0
  6. package/bench/molbench.bench.ts +75 -0
  7. package/{tests/bench/system.ts → bench/system.bench.ts} +3 -3
  8. package/build/compiler/array.d.ts +1 -1
  9. package/build/compiler/constants.d.ts +7 -6
  10. package/build/compiler/constants.js +6 -7
  11. package/build/compiler/object.d.ts +1 -1
  12. package/build/compiler/object.js +1 -2
  13. package/build/compiler/primitives.d.ts +1 -1
  14. package/build/constants.d.ts +3 -1
  15. package/build/constants.js +3 -1
  16. package/build/reactive/array.d.ts +7 -3
  17. package/build/reactive/array.js +32 -24
  18. package/build/reactive/index.d.ts +2 -2
  19. package/build/reactive/index.js +1 -1
  20. package/build/reactive/object.d.ts +4 -4
  21. package/build/reactive/object.js +8 -23
  22. package/build/system.d.ts +15 -6
  23. package/build/system.js +432 -69
  24. package/build/types.d.ts +22 -4
  25. package/package.json +10 -7
  26. package/src/compiler/array.ts +1 -1
  27. package/src/compiler/constants.ts +8 -6
  28. package/src/compiler/index.ts +2 -1
  29. package/src/compiler/object.ts +2 -2
  30. package/src/compiler/plugins/vite.ts +1 -0
  31. package/src/compiler/primitives.ts +1 -1
  32. package/src/constants.ts +6 -2
  33. package/src/reactive/array.ts +50 -35
  34. package/src/reactive/index.ts +6 -6
  35. package/src/reactive/object.ts +16 -41
  36. package/src/system.ts +635 -80
  37. package/src/types.ts +38 -9
  38. package/test/async-computed.test.ts +409 -0
  39. package/test/async-errors.test.ts +146 -0
  40. package/test/async-hardening.test.ts +73 -0
  41. package/test/async-iterable.test.ts +221 -0
  42. package/test/async-nested.test.ts +19 -0
  43. package/test/deep-graphs.test.ts +215 -0
  44. package/{tests/effects.ts → test/effects.test.ts} +122 -0
  45. package/test/equals.test.ts +142 -0
  46. package/test/errors.test.ts +201 -0
  47. package/test/flush.test.ts +185 -0
  48. package/test/glitch-freedom.test.ts +115 -0
  49. package/test/invalidate.test.ts +147 -0
  50. package/test/lib/wait-for.ts +28 -0
  51. package/test/pending-writes.test.ts +139 -0
  52. package/{tests/reactive.ts → test/reactive/reactive.test.ts} +20 -19
  53. package/test/read-dedup.test.ts +120 -0
  54. package/test/signal-selector.test.ts +187 -0
  55. package/{tests/system.ts → test/system.test.ts} +210 -19
  56. package/test/tsconfig.json +16 -0
  57. package/test/untrack.test.ts +146 -0
  58. package/vitest.config.ts +2 -2
  59. package/tests/async-computed.ts +0 -239
  60. /package/{tests/bench/array.ts → bench/reactive/array.bench.ts} +0 -0
  61. /package/{tests/bench/reactive-object.ts → bench/reactive/reactive-object.bench.ts} +0 -0
  62. /package/{tests → bench}/tsconfig.json +0 -0
  63. /package/{tests/compiler.ts → test/compiler/compiler.test.ts} +0 -0
  64. /package/{tests/primitives.ts → test/primitives.test.ts} +0 -0
  65. /package/{tests/array.ts → test/reactive/array.test.ts} +0 -0
  66. /package/{tests/nested.ts → test/reactive/nested.test.ts} +0 -0
  67. /package/{tests/objects.ts → test/reactive/objects.test.ts} +0 -0
package/build/types.d.ts CHANGED
@@ -5,15 +5,23 @@ interface Computed<T> {
5
5
  cleanup: VoidFunction | VoidFunction[] | null;
6
6
  deps: Link | null;
7
7
  depsTail: Link | null;
8
+ disposal: VoidFunction | null;
9
+ equals: ((a: unknown, b: unknown) => boolean) | null;
10
+ error: unknown;
8
11
  fn: (onCleanup: (fn: VoidFunction) => typeof fn) => T;
12
+ gv: number;
9
13
  height: number;
10
14
  nextHeap: Computed<unknown> | undefined;
11
15
  prevHeap: Computed<unknown>;
16
+ rv: number;
12
17
  state: number;
13
18
  subs: Link | null;
14
19
  subsTail: Link | null;
15
20
  value: T;
16
21
  }
22
+ type ComputedResult<T> = T extends Promise<any> | AsyncIterable<any> ? Computed<Settled<T>> & {
23
+ pending: Signal<boolean>;
24
+ } : Computed<Settled<T>>;
17
25
  interface Link {
18
26
  dep: Signal<unknown> | Computed<unknown>;
19
27
  nextDep: Link | null;
@@ -23,16 +31,26 @@ interface Link {
23
31
  version: number;
24
32
  }
25
33
  declare const READONLY: unique symbol;
26
- type Reactive<T> = T extends (...args: unknown[]) => Promise<infer R> ? (R | undefined) & {
27
- readonly [READONLY]: true;
28
- } : T extends (...args: any[]) => infer R ? R & {
34
+ type Reactive<T> = T extends (...args: never[]) => infer R ? Settled<R> & {
29
35
  readonly [READONLY]: true;
30
36
  } : T extends (infer U)[] ? U[] & Pick<ReactiveArray<U>, 'clear' | 'dispose' | 'on' | 'once'> : T extends Record<PropertyKey, unknown> ? {
31
37
  [K in keyof T]: T[K] extends (infer U)[] ? Reactive<U[]> : T[K];
32
38
  } & {
33
39
  dispose: VoidFunction;
34
40
  } : T;
41
+ type SelectorSignal<T> = Signal<boolean> & {
42
+ key: T;
43
+ parent: Signal<T>;
44
+ };
45
+ type Settled<T> = T extends Promise<infer U> ? Awaited<U> | undefined : T extends AsyncIterable<infer U> ? U | undefined : T;
35
46
  type Signal<T> = {
47
+ equals: ((a: unknown, b: unknown) => boolean) | null;
48
+ key: unknown;
49
+ keys: Map<T, SelectorSignal<T>> | null;
50
+ nextPending: Signal<unknown> | null;
51
+ parent: Signal<unknown> | undefined;
52
+ rv: number;
53
+ state: number;
36
54
  subs: Link | null;
37
55
  subsTail: Link | null;
38
56
  type: typeof SIGNAL;
@@ -43,4 +61,4 @@ interface TransformResult {
43
61
  code: string;
44
62
  sourceFile: ts.SourceFile;
45
63
  }
46
- export type { Computed, Link, Reactive, Signal, TransformResult };
64
+ export type { Computed, ComputedResult, Link, Reactive, SelectorSignal, Settled, Signal, TransformResult };
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "author": "ICJR",
3
3
  "dependencies": {
4
- "@esportsplus/utilities": "^0.27.3"
4
+ "@esportsplus/utilities": "^0.28.0"
5
5
  },
6
6
  "devDependencies": {
7
- "@esportsplus/typescript": "^0.29.1",
8
- "@types/node": "^25.6.0",
9
- "vite": "^8.0.8",
10
- "vitest": "^4.1.4"
7
+ "@esportsplus/typescript": "^0.29.5",
8
+ "@types/node": "^26.1.1",
9
+ "vite": "^8.1.5",
10
+ "vitest": "^4.1.10"
11
11
  },
12
12
  "exports": {
13
13
  ".": {
@@ -36,10 +36,13 @@
36
36
  },
37
37
  "type": "module",
38
38
  "types": "build/index.d.ts",
39
- "version": "0.31.3",
39
+ "version": "0.33.0",
40
40
  "scripts": {
41
+ "agent:bench": "vitest bench --run",
42
+ "agent:test": "tsc --noEmit && vitest run",
43
+ "bench": "vitest bench --run",
41
44
  "build": "tsc",
42
- "build:test": "pnpm build && vite build --config test/vite.config.ts",
45
+ "test": "vitest run",
43
46
  "-": "-"
44
47
  }
45
48
  }
@@ -1,6 +1,6 @@
1
- import type { ReplacementIntent } from '@esportsplus/typescript/compiler';
2
1
  import { ts } from '@esportsplus/typescript';
3
2
  import { ast, imports } from '@esportsplus/typescript/compiler';
3
+ import type { ReplacementIntent } from '@esportsplus/typescript/compiler';
4
4
  import { ENTRYPOINT, NAMESPACE, PACKAGE_NAME, TYPES } from './constants';
5
5
  import type { Bindings } from './types';
6
6
 
@@ -8,12 +8,14 @@ const ENTRYPOINT_REGEX = /\breactive\b/;
8
8
  const NAMESPACE = uid('reactivity');
9
9
 
10
10
 
11
- const enum TYPES {
12
- Array,
13
- Computed,
14
- Object,
15
- Signal
16
- }
11
+ const TYPES = {
12
+ Array: 0,
13
+ Computed: 1,
14
+ Object: 2,
15
+ Signal: 3
16
+ } as const;
17
+
18
+ type TYPES = typeof TYPES[keyof typeof TYPES];
17
19
 
18
20
 
19
21
  export { ENTRYPOINT, ENTRYPOINT_REGEX, NAMESPACE, TYPES };
@@ -1,8 +1,9 @@
1
- import type { ImportIntent, ReplacementIntent, TransformContext } from '@esportsplus/typescript/compiler';
2
1
  import { ts } from '@esportsplus/typescript';
3
2
  import { imports } from '@esportsplus/typescript/compiler';
3
+ import type { ImportIntent, ReplacementIntent, TransformContext } from '@esportsplus/typescript/compiler';
4
4
  import { ENTRYPOINT, NAMESPACE, PACKAGE_NAME } from './constants';
5
5
  import type { Bindings } from './types';
6
+
6
7
  import array from './array';
7
8
  import object from './object';
8
9
  import primitives from './primitives';
@@ -1,6 +1,6 @@
1
- import { code, imports, type ReplacementIntent } from '@esportsplus/typescript/compiler';
2
1
  import { ts } from '@esportsplus/typescript';
3
- import { uid } from '@esportsplus/typescript/compiler';
2
+ import { code, imports, uid } from '@esportsplus/typescript/compiler';
3
+ import type { ReplacementIntent } from '@esportsplus/typescript/compiler';
4
4
  import { ENTRYPOINT, NAMESPACE, PACKAGE_NAME, TYPES } from './constants';
5
5
  import type { Bindings } from './types';
6
6
 
@@ -1,5 +1,6 @@
1
1
  import { plugin } from '@esportsplus/typescript/compiler';
2
2
  import { PACKAGE_NAME } from '../constants';
3
+
3
4
  import reactivity from '..';
4
5
 
5
6
 
@@ -1,5 +1,5 @@
1
- import type { ReplacementIntent } from '@esportsplus/typescript/compiler';
2
1
  import { ts } from '@esportsplus/typescript';
2
+ import type { ReplacementIntent } from '@esportsplus/typescript/compiler';
3
3
  import { NAMESPACE, TYPES } from './constants';
4
4
  import type { Bindings } from './types';
5
5
 
package/src/constants.ts CHANGED
@@ -28,14 +28,18 @@ const STATE_IN_HEAP = 1 << 3;
28
28
 
29
29
  const STATE_COMPUTED = 1 << 4;
30
30
 
31
+ const STATE_ERROR = 1 << 5;
32
+
33
+ const STATE_EFFECT = 1 << 6;
34
+
31
35
  const STATE_NOTIFY_MASK = (STATE_CHECK | STATE_DIRTY);
32
36
 
33
37
 
34
38
  export {
35
39
  COMPUTED,
36
- REACTIVE_ARRAY, REACTIVE_OBJECT,
37
40
  PACKAGE_NAME,
41
+ REACTIVE_ARRAY, REACTIVE_OBJECT,
38
42
  SIGNAL,
39
43
  STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED,
40
- STATE_CHECK, STATE_COMPUTED, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_NOTIFY_MASK, STATE_RECOMPUTING
44
+ STATE_CHECK, STATE_COMPUTED, STATE_DIRTY, STATE_EFFECT, STATE_ERROR, STATE_IN_HEAP, STATE_NONE, STATE_NOTIFY_MASK, STATE_RECOMPUTING
41
45
  };
@@ -1,6 +1,6 @@
1
1
  import { isArray } from '@esportsplus/utilities';
2
- import { read, signal, write } from '~/system';
3
2
  import { REACTIVE_ARRAY } from '~/constants';
3
+ import { read, signal, write } from '~/system';
4
4
  import type { Signal } from '~/types';
5
5
  import { isReactiveObject } from './object';
6
6
 
@@ -42,7 +42,9 @@ type Listener<V> = {
42
42
  (value: V): void;
43
43
  };
44
44
 
45
- type Listeners = Record<string, (Listener<any> | null)[]>;
45
+ type AnyListener<T> = Listener<Events<T>[keyof Events<T>]>;
46
+
47
+ type Listeners<T> = { [K in keyof Events<T>]?: (AnyListener<T> | null)[] };
46
48
 
47
49
 
48
50
  function dispose(value: unknown) {
@@ -52,10 +54,13 @@ function dispose(value: unknown) {
52
54
  }
53
55
 
54
56
 
57
+ // Derived arrays (splice removals, map/filter/slice) must be plain Arrays: species-creating a
58
+ // ReactiveArray runs the reactive constructor per call and seeds _length from the length argument.
55
59
  class ReactiveArray<T> extends Array<T> {
60
+
56
61
  private _length: Signal<number>;
57
62
 
58
- listeners: Listeners = {};
63
+ listeners: Listeners<T> = {};
59
64
 
60
65
 
61
66
  constructor(...items: T[]) {
@@ -64,6 +69,11 @@ class ReactiveArray<T> extends Array<T> {
64
69
  }
65
70
 
66
71
 
72
+ static get [Symbol.species]() {
73
+ return Array;
74
+ }
75
+
76
+
67
77
  get $length() {
68
78
  return read(this._length);
69
79
  }
@@ -130,7 +140,7 @@ class ReactiveArray<T> extends Array<T> {
130
140
  return this;
131
141
  }
132
142
 
133
- dispatch<K extends keyof Events<T>, V>(event: K, value?: V) {
143
+ dispatch<K extends keyof Events<T>>(event: K, value?: Events<T>[K]) {
134
144
  let listeners = this.listeners[event];
135
145
 
136
146
  if (!listeners) {
@@ -147,7 +157,7 @@ class ReactiveArray<T> extends Array<T> {
147
157
  }
148
158
 
149
159
  try {
150
- listener(value);
160
+ listener(value as Events<T>[K]);
151
161
 
152
162
  if (listener.once !== undefined) {
153
163
  dirty = true;
@@ -176,10 +186,11 @@ class ReactiveArray<T> extends Array<T> {
176
186
  }
177
187
 
178
188
  on<K extends keyof Events<T>>(event: K, listener: Listener<Events<T>[K]>) {
179
- let listeners = this.listeners[event];
189
+ let entry = listener as AnyListener<T>,
190
+ listeners = this.listeners[event];
180
191
 
181
192
  if (listeners === undefined) {
182
- this.listeners[event] = [listener];
193
+ this.listeners[event] = [entry];
183
194
  }
184
195
  else {
185
196
  let hole = listeners.length;
@@ -187,7 +198,7 @@ class ReactiveArray<T> extends Array<T> {
187
198
  for (let i = 0, n = hole; i < n; i++) {
188
199
  let l = listeners[i];
189
200
 
190
- if (l === listener) {
201
+ if (l === entry) {
191
202
  return;
192
203
  }
193
204
  else if (l === null && hole === n) {
@@ -195,7 +206,7 @@ class ReactiveArray<T> extends Array<T> {
195
206
  }
196
207
  }
197
208
 
198
- listeners[hole] = listener;
209
+ listeners[hole] = entry;
199
210
 
200
211
  while (listeners.length && listeners[listeners.length - 1] === null) {
201
212
  listeners.pop();
@@ -214,7 +225,6 @@ class ReactiveArray<T> extends Array<T> {
214
225
  if (item !== undefined) {
215
226
  dispose(item);
216
227
  write(this._length, this.length);
217
-
218
228
  this.dispatch('pop', { item });
219
229
  }
220
230
 
@@ -229,6 +239,7 @@ class ReactiveArray<T> extends Array<T> {
229
239
  let length = super.push(...items);
230
240
 
231
241
  write(this._length, length);
242
+
232
243
  this.dispatch('push', { items });
233
244
 
234
245
  return length;
@@ -247,7 +258,6 @@ class ReactiveArray<T> extends Array<T> {
247
258
  if (item !== undefined) {
248
259
  dispose(item);
249
260
  write(this._length, this.length);
250
-
251
261
  this.dispatch('shift', { item });
252
262
  }
253
263
 
@@ -255,41 +265,46 @@ class ReactiveArray<T> extends Array<T> {
255
265
  }
256
266
 
257
267
  sort(fn?: (a: T, b: T) => number) {
258
- let n = this.length,
259
- before = new Array(n) as T[];
260
-
261
- for (let i = 0; i < n; i++) {
262
- before[i] = this[i];
268
+ if (this.listeners.sort === undefined) {
269
+ super.sort(fn);
263
270
  }
271
+ else {
272
+ let n = this.length,
273
+ before = new Array(n) as T[];
264
274
 
265
- super.sort(fn);
275
+ for (let i = 0; i < n; i++) {
276
+ before[i] = this[i];
277
+ }
266
278
 
267
- let buckets = new Map<any, number[]>(),
268
- order = new Array(n);
279
+ super.sort(fn);
269
280
 
270
- for (let i = 0; i < n; i++) {
271
- let value = before[i],
272
- list = buckets.get(value);
281
+ let buckets = new Map<T, number[]>(),
282
+ order = new Array(n);
273
283
 
274
- if (!list) {
275
- buckets.set(value, [i]);
276
- }
277
- else {
278
- list.push(i);
284
+ for (let i = 0; i < n; i++) {
285
+ let value = before[i],
286
+ list = buckets.get(value);
287
+
288
+ if (!list) {
289
+ buckets.set(value, [i]);
290
+ }
291
+ else {
292
+ list.push(i);
293
+ }
279
294
  }
280
- }
281
295
 
282
- for (let i = 0; i < n; i++) {
283
- let list = buckets.get(this[i])!;
296
+ for (let i = 0; i < n; i++) {
297
+ let list = buckets.get(this[i])!;
284
298
 
285
- order[i] = list.length === 1 ? list[0] : list[list.length - 1];
299
+ order[i] = list.length === 1 ? list[0] : list[list.length - 1];
286
300
 
287
- if (list.length > 1) {
288
- list.pop();
301
+ if (list.length > 1) {
302
+ list.pop();
303
+ }
289
304
  }
290
- }
291
305
 
292
- this.dispatch('sort', { order });
306
+ this.dispatch('sort', { order });
307
+ }
293
308
 
294
309
  return this;
295
310
  }
@@ -1,14 +1,14 @@
1
1
  import { onCleanup, root } from '@esportsplus/reactivity';
2
2
  import { isArray, isObject } from '@esportsplus/utilities';
3
- import { Reactive } from '~/types';
3
+ import { PACKAGE_NAME } from '~/constants';
4
+ import type { Reactive } from '~/types';
4
5
  import { ReactiveArray } from './array';
5
6
  import { ReactiveObject } from './object';
6
- import { PACKAGE_NAME } from '~/constants';
7
7
 
8
8
 
9
9
  type Guard<T> =
10
10
  T extends Record<PropertyKey, unknown>
11
- ? T extends { dispose: any }
11
+ ? T extends { dispose: unknown }
12
12
  ? { never: '[ dispose ] is a reserved key' }
13
13
  : T
14
14
  : never;
@@ -23,10 +23,10 @@ function reactive<T>(input: T): Reactive<T> {
23
23
  let response: Reactive<T> | undefined;
24
24
 
25
25
  if (isObject(input)) {
26
- response = new ReactiveObject(input) as any as Reactive<T>;
26
+ response = new ReactiveObject(input) as unknown as Reactive<T>;
27
27
  }
28
28
  else if (isArray(input)) {
29
- response = new ReactiveArray(...input) as any as Reactive<T>;
29
+ response = new ReactiveArray(...input) as unknown as Reactive<T>;
30
30
  }
31
31
 
32
32
  if (response) {
@@ -41,7 +41,7 @@ function reactive<T>(input: T): Reactive<T> {
41
41
  });
42
42
 
43
43
  if (dispose) {
44
- onCleanup(() => (value as any as { dispose: VoidFunction }).dispose());
44
+ onCleanup(() => (value as unknown as { dispose: VoidFunction }).dispose());
45
45
  }
46
46
 
47
47
  return value;
@@ -1,7 +1,7 @@
1
- import { defineProperty, isArray, isPromise } from '@esportsplus/utilities';
2
- import { computed, dispose, effect, read, root, signal, write } from '~/system';
3
- import { Computed, Signal } from '~/types';
1
+ import { defineProperty, isArray } from '@esportsplus/utilities';
4
2
  import { COMPUTED, REACTIVE_ARRAY, REACTIVE_OBJECT, SIGNAL } from '~/constants';
3
+ import { computed, dispose, read, root, signal, write } from '~/system';
4
+ import { Computed } from '~/types';
5
5
  import { ReactiveArray } from './array';
6
6
 
7
7
 
@@ -32,10 +32,7 @@ class ReactiveObject<T extends Record<PropertyKey, unknown>> {
32
32
  continue;
33
33
  }
34
34
 
35
- if (value == null || type !== 'object') {
36
- // Skip isArray when possible
37
- }
38
- else if (isArray(value)) {
35
+ if (value != null && type === 'object' && isArray(value)) {
39
36
  defineProperty(this, key, {
40
37
  enumerable: true,
41
38
  value: this[REACTIVE_ARRAY](value)
@@ -59,44 +56,22 @@ class ReactiveObject<T extends Record<PropertyKey, unknown>> {
59
56
  }
60
57
 
61
58
 
62
- protected [REACTIVE_ARRAY]<U>(value: U[]): ReactiveArray<U> {
63
- let node = new ReactiveArray(...value);
64
-
65
- (this.disposers ??= []).push( () => node.dispose() );
66
-
67
- return node;
68
- }
69
-
70
59
  protected [COMPUTED]<T extends Computed<ReturnType<T>>['fn']>(value: T) {
71
60
  return root(() => {
72
- let node: Computed<ReturnType<T>> | Signal<ReturnType<T> | undefined> = computed(value);
73
-
74
- if (isPromise(node.value)) {
75
- let factory = node as Computed<ReturnType<T>>,
76
- out = signal<ReturnType<T> | undefined>(undefined),
77
- v = 0;
78
-
79
- (this.disposers ??= []).push(
80
- effect(() => {
81
- let id = ++v;
61
+ let node = computed(value);
82
62
 
83
- (read(factory) as Promise<ReturnType<T>>).then((resolved) => {
84
- if (id !== v) {
85
- return;
86
- }
63
+ (this.disposers ??= []).push(() => dispose(node));
87
64
 
88
- write(out as Signal<typeof resolved>, resolved);
89
- });
90
- })
91
- );
65
+ return node;
66
+ });
67
+ }
92
68
 
93
- return out;
94
- }
69
+ protected [REACTIVE_ARRAY]<U>(value: U[]): ReactiveArray<U> {
70
+ let node = new ReactiveArray(...value);
95
71
 
96
- (this.disposers ??= []).push(() => dispose(node as Computed<ReturnType<T>>));
72
+ (this.disposers ??= []).push( () => node.dispose() );
97
73
 
98
- return node;
99
- });
74
+ return node;
100
75
  }
101
76
 
102
77
  protected [SIGNAL]<T>(value: T) {
@@ -121,9 +96,9 @@ class ReactiveObject<T extends Record<PropertyKey, unknown>> {
121
96
  Object.defineProperty(ReactiveObject.prototype, REACTIVE_OBJECT, { value: true });
122
97
 
123
98
 
124
- const isReactiveObject = (value: any): value is ReactiveObject<any> => {
125
- return typeof value === 'object' && value !== null && value[REACTIVE_OBJECT] === true;
99
+ const isReactiveObject = (value: unknown): value is ReactiveObject<Record<PropertyKey, unknown>> => {
100
+ return typeof value === 'object' && value !== null && (value as Record<PropertyKey, unknown>)[REACTIVE_OBJECT] === true;
126
101
  };
127
102
 
128
103
 
129
- export { isReactiveObject, ReactiveObject };
104
+ export { isReactiveObject, ReactiveObject };