|
1 | | -import { type Operation, resource } from "effection"; |
| 1 | +import { type Operation, createSignal, resource } from "effection"; |
| 2 | +import { List } from "immutable"; |
2 | 3 |
|
3 | 4 | import { is } from "./helpers.ts"; |
4 | 5 | import type { ValueSignal } from "./types.ts"; |
5 | | -import { createValueSignal } from "./value.ts"; |
6 | 6 |
|
7 | 7 | /** |
8 | 8 | * Interface for return value of {@link createArraySignal}. |
@@ -49,48 +49,51 @@ export function createArraySignal<T>( |
49 | 49 | initial: Iterable<T>, |
50 | 50 | ): Operation<ArraySignal<T>> { |
51 | 51 | return resource(function* (provide) { |
52 | | - const signal = yield* createValueSignal(snapshotArray(initial), { |
53 | | - equals: areArraysEqual, |
54 | | - }); |
| 52 | + const signal = createSignal<T[], void>(); |
| 53 | + const ref = { |
| 54 | + current: List.of<T>(...initial), |
| 55 | + }; |
| 56 | + |
| 57 | + function set(value: Iterable<T>) { |
| 58 | + if (ref.current.equals(List.of<T>(...value))) { |
| 59 | + return ref.current.toArray(); |
| 60 | + } |
55 | 61 |
|
56 | | - function set(value: Iterable<T>): T[] { |
57 | | - return signal.set(snapshotArray(value)).slice(); |
| 62 | + ref.current = List.of<T>(...value); |
| 63 | + signal.send(ref.current.toArray()); |
| 64 | + return ref.current.toArray(); |
58 | 65 | } |
59 | 66 |
|
60 | 67 | const array: ArraySignal<T> = { |
61 | 68 | [Symbol.iterator]: signal[Symbol.iterator], |
62 | 69 | set, |
63 | 70 | update(updater) { |
64 | | - return set(updater(signal.valueOf().slice())); |
| 71 | + return set(updater(ref.current.toArray())); |
65 | 72 | }, |
66 | 73 | push(...args: T[]) { |
67 | | - return signal.set(snapshotArray([...signal.valueOf(), ...args])).length; |
| 74 | + ref.current = ref.current.push(...args); |
| 75 | + signal.send(ref.current.toArray()); |
| 76 | + return ref.current.size; |
68 | 77 | }, |
69 | 78 | *shift() { |
70 | 79 | yield* is(array, (array) => array.length > 0); |
71 | | - const [value, ...rest] = signal.valueOf(); |
72 | | - signal.set(snapshotArray(rest)); |
73 | | - return value!; |
| 80 | + const value = ref.current.first()!; |
| 81 | + ref.current = ref.current.shift(); |
| 82 | + signal.send(ref.current.toArray()); |
| 83 | + return value; |
74 | 84 | }, |
75 | 85 | valueOf() { |
76 | | - return signal.valueOf().slice(); |
| 86 | + return ref.current.toArray(); |
77 | 87 | }, |
78 | 88 | get length() { |
79 | | - return signal.valueOf().length; |
| 89 | + return ref.current.size; |
80 | 90 | }, |
81 | 91 | }; |
82 | 92 |
|
83 | | - yield* provide(array); |
| 93 | + try { |
| 94 | + yield* provide(array); |
| 95 | + } finally { |
| 96 | + signal.close(); |
| 97 | + } |
84 | 98 | }); |
85 | 99 | } |
86 | | - |
87 | | -function snapshotArray<T>(value: Iterable<T>): T[] { |
88 | | - return Object.freeze([...value]) as T[]; |
89 | | -} |
90 | | - |
91 | | -function areArraysEqual<T>(current: readonly T[], next: readonly T[]): boolean { |
92 | | - return ( |
93 | | - current.length === next.length && |
94 | | - current.every((value, index) => Object.is(value, next[index])) |
95 | | - ); |
96 | | -} |
|
0 commit comments