@ng-org/alien-deepsignals 0.1.2-alpha.10 → 0.1.2-alpha.12
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/core.d.ts +5 -1
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +11 -11
- package/dist/deepSignal.d.ts +1 -1
- package/dist/deepSignal.d.ts.map +1 -1
- package/dist/deepSignal.js +16 -27
- package/dist/hooks/react/index.js +2 -8
- package/dist/hooks/react/useDeepSignal.d.ts +2 -2
- package/dist/hooks/react/useDeepSignal.d.ts.map +1 -1
- package/dist/hooks/react/useDeepSignal.js +11 -13
- package/dist/hooks/svelte/index.js +2 -8
- package/dist/hooks/svelte/useDeepSignal.svelte.d.ts +1 -1
- package/dist/hooks/svelte/useDeepSignal.svelte.d.ts.map +1 -1
- package/dist/hooks/svelte/useDeepSignal.svelte.js +6 -9
- package/dist/hooks/svelte4/index.js +2 -8
- package/dist/hooks/svelte4/useDeepSignal.svelte.d.ts +1 -1
- package/dist/hooks/svelte4/useDeepSignal.svelte.d.ts.map +1 -1
- package/dist/hooks/svelte4/useDeepSignal.svelte.js +14 -17
- package/dist/hooks/vue/index.d.ts +1 -1
- package/dist/hooks/vue/index.d.ts.map +1 -1
- package/dist/hooks/vue/index.js +2 -8
- package/dist/hooks/vue/useDeepSignal.d.ts +1 -1
- package/dist/hooks/vue/useDeepSignal.d.ts.map +1 -1
- package/dist/hooks/vue/useDeepSignal.js +6 -9
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -27
- package/dist/iteratorHelpers.js +2 -6
- package/dist/test/frontend/astro-app/src/components/ReactPanel.d.ts.map +1 -1
- package/dist/test/frontend/astro-app/src/components/ReactPanel.jsx +13 -51
- package/dist/test/frontend/playwright/crossFrameworkHooks.spec.js +24 -26
- package/dist/test/frontend/utils/mockData.js +16 -21
- package/dist/test/frontend/utils/paths.js +2 -6
- package/dist/test/frontend/utils/renderMetrics.js +5 -12
- package/dist/test/frontend/utils/state.d.ts +1 -1
- package/dist/test/frontend/utils/state.js +13 -17
- package/dist/test/lib/deepSignalOptions.test.js +66 -68
- package/dist/test/lib/index.test.js +373 -375
- package/dist/test/lib/misc.test.js +98 -100
- package/dist/test/lib/watch.test.js +355 -357
- package/dist/types.d.ts +5 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -2
- package/dist/watch.d.ts +1 -1
- package/dist/watch.d.ts.map +1 -1
- package/dist/watch.js +6 -9
- package/package.json +2 -1
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
// Copyright (c) 2025 Laurin Weger, Par le Peuple, NextGraph.org developers
|
|
3
2
|
// All rights reserved.
|
|
4
3
|
// Licensed under the Apache License, Version 2.0
|
|
@@ -8,48 +7,47 @@
|
|
|
8
7
|
// notice may not be copied, modified, or distributed except
|
|
9
8
|
// according to those terms.
|
|
10
9
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
(0, vitest_1.describe)("deepsignal/core", () => {
|
|
10
|
+
import { deepSignal, shallow } from "../../index.js";
|
|
11
|
+
import { describe, it, expect, beforeEach } from "vitest";
|
|
12
|
+
import { effect } from "../../index.js";
|
|
13
|
+
describe("deepsignal/core", () => {
|
|
16
14
|
let nested = { b: 2 };
|
|
17
15
|
let array = [3, nested];
|
|
18
16
|
let state = { a: 1, nested, array };
|
|
19
|
-
let store =
|
|
17
|
+
let store = deepSignal(state);
|
|
20
18
|
const window = globalThis;
|
|
21
|
-
|
|
19
|
+
beforeEach(() => {
|
|
22
20
|
nested = { b: 2 };
|
|
23
21
|
array = [3, nested];
|
|
24
22
|
state = { a: 1, nested, array };
|
|
25
|
-
store =
|
|
23
|
+
store = deepSignal(state);
|
|
26
24
|
});
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
const store =
|
|
25
|
+
describe("get - plain", () => {
|
|
26
|
+
it("should return plain objects/arrays", () => {
|
|
27
|
+
expect(store.nested).to.deep.equal({ b: 2 });
|
|
28
|
+
expect(store.array).to.deep.equal([3, { b: 2 }]);
|
|
29
|
+
expect(store.array[1]).to.deep.equal({ b: 2 });
|
|
30
|
+
});
|
|
31
|
+
it("should return plain primitives", () => {
|
|
32
|
+
expect(store.a).to.equal(1);
|
|
33
|
+
expect(store.nested.b).to.equal(2);
|
|
34
|
+
expect(store.array[0]).to.equal(3);
|
|
35
|
+
expect(typeof store.array[1] === "object" && store.array[1].b).to.equal(2);
|
|
36
|
+
expect(store.array.length).to.equal(2);
|
|
37
|
+
});
|
|
38
|
+
it("should support reading from getters", () => {
|
|
39
|
+
const store = deepSignal({
|
|
42
40
|
counter: 1,
|
|
43
41
|
get double() {
|
|
44
42
|
return store.counter * 2;
|
|
45
43
|
},
|
|
46
44
|
});
|
|
47
|
-
|
|
45
|
+
expect(store.double).to.equal(2);
|
|
48
46
|
store.counter = 2;
|
|
49
|
-
|
|
47
|
+
expect(store.double).to.equal(4);
|
|
50
48
|
});
|
|
51
|
-
|
|
52
|
-
const store =
|
|
49
|
+
it("should support getters returning other parts of the state", () => {
|
|
50
|
+
const store = deepSignal({
|
|
53
51
|
switch: "a",
|
|
54
52
|
a: { data: "a" },
|
|
55
53
|
b: { data: "b" },
|
|
@@ -57,12 +55,12 @@ const __1 = require("../..");
|
|
|
57
55
|
return store.switch === "a" ? store.a : store.b;
|
|
58
56
|
},
|
|
59
57
|
});
|
|
60
|
-
|
|
58
|
+
expect(store.aOrB.data).to.equal("a");
|
|
61
59
|
store.switch = "b";
|
|
62
|
-
|
|
60
|
+
expect(store.aOrB.data).to.equal("b");
|
|
63
61
|
});
|
|
64
|
-
|
|
65
|
-
const state =
|
|
62
|
+
it("should support getters using ownKeys traps", () => {
|
|
63
|
+
const state = deepSignal({
|
|
66
64
|
x: {
|
|
67
65
|
a: 1,
|
|
68
66
|
b: 2,
|
|
@@ -71,10 +69,10 @@ const __1 = require("../..");
|
|
|
71
69
|
return Object.values(state.x);
|
|
72
70
|
},
|
|
73
71
|
});
|
|
74
|
-
|
|
72
|
+
expect(state.y).to.deep.equal([1, 2]);
|
|
75
73
|
});
|
|
76
|
-
|
|
77
|
-
const store =
|
|
74
|
+
it("should work with normal functions", () => {
|
|
75
|
+
const store = deepSignal({
|
|
78
76
|
value: 1,
|
|
79
77
|
isBigger: (newValue) => store.value < newValue,
|
|
80
78
|
sum(newValue) {
|
|
@@ -84,25 +82,25 @@ const __1 = require("../..");
|
|
|
84
82
|
store.value = newValue;
|
|
85
83
|
},
|
|
86
84
|
});
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
expect(store.isBigger(2)).to.equal(true);
|
|
86
|
+
expect(store.sum(2)).to.equal(3);
|
|
87
|
+
expect(store.value).to.equal(1);
|
|
90
88
|
store.replace(2);
|
|
91
|
-
|
|
89
|
+
expect(store.value).to.equal(2);
|
|
92
90
|
});
|
|
93
91
|
});
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
92
|
+
describe("set", () => {
|
|
93
|
+
it("should update like plain objects/arrays", () => {
|
|
94
|
+
expect(store.a).to.equal(1);
|
|
95
|
+
expect(store.nested.b).to.equal(2);
|
|
98
96
|
store.a = 2;
|
|
99
97
|
store.nested.b = 3;
|
|
100
|
-
|
|
101
|
-
|
|
98
|
+
expect(store.a).to.equal(2);
|
|
99
|
+
expect(store.nested.b).to.equal(3);
|
|
102
100
|
});
|
|
103
101
|
// TODO: Remove the .value access semantics.
|
|
104
|
-
|
|
105
|
-
const store =
|
|
102
|
+
it("should support setting values with setters", () => {
|
|
103
|
+
const store = deepSignal({
|
|
106
104
|
counter: 1,
|
|
107
105
|
get double() {
|
|
108
106
|
return store.counter * 2;
|
|
@@ -111,26 +109,26 @@ const __1 = require("../..");
|
|
|
111
109
|
store.counter = val / 2;
|
|
112
110
|
},
|
|
113
111
|
});
|
|
114
|
-
|
|
112
|
+
expect(store.counter).to.equal(1);
|
|
115
113
|
store.double = 4;
|
|
116
|
-
|
|
114
|
+
expect(store.counter).to.equal(2);
|
|
117
115
|
});
|
|
118
|
-
|
|
116
|
+
it("should update array length", () => {
|
|
119
117
|
let state = { a: 1, nested, array };
|
|
120
|
-
let store =
|
|
121
|
-
|
|
118
|
+
let store = deepSignal(state);
|
|
119
|
+
expect(store.array.length).to.equal(2);
|
|
122
120
|
store.array.push(4);
|
|
123
|
-
|
|
121
|
+
expect(store.array.length).to.equal(3);
|
|
124
122
|
store.array.splice(1, 2);
|
|
125
|
-
|
|
123
|
+
expect(store.array.length).to.equal(1);
|
|
126
124
|
});
|
|
127
|
-
|
|
128
|
-
|
|
125
|
+
it("should update when mutations happen", () => {
|
|
126
|
+
expect(store.a).to.equal(1);
|
|
129
127
|
store.a = 11;
|
|
130
|
-
|
|
128
|
+
expect(store.a).to.equal(11);
|
|
131
129
|
});
|
|
132
|
-
|
|
133
|
-
const store =
|
|
130
|
+
it("should support setting getters on the fly", () => {
|
|
131
|
+
const store = deepSignal({
|
|
134
132
|
counter: 1,
|
|
135
133
|
});
|
|
136
134
|
Object.defineProperty(store, "double", {
|
|
@@ -138,112 +136,112 @@ const __1 = require("../..");
|
|
|
138
136
|
return store.counter * 2;
|
|
139
137
|
},
|
|
140
138
|
});
|
|
141
|
-
|
|
139
|
+
expect(store.double).to.equal(2);
|
|
142
140
|
store.counter = 2;
|
|
143
|
-
|
|
141
|
+
expect(store.double).to.equal(4);
|
|
144
142
|
});
|
|
145
|
-
|
|
146
|
-
const store =
|
|
143
|
+
it("should copy object like plain JavaScript", () => {
|
|
144
|
+
const store = deepSignal({
|
|
147
145
|
b: { id: 1, nested: { id: 1 } },
|
|
148
146
|
});
|
|
149
147
|
store.a = store.b;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
148
|
+
expect(store.a.id).to.equal(1);
|
|
149
|
+
expect(store.b.id).to.equal(1);
|
|
150
|
+
expect(store.a.nested.id).to.equal(1);
|
|
151
|
+
expect(store.b.nested.id).to.equal(1);
|
|
154
152
|
store.a.id = 2;
|
|
155
153
|
store.a.nested.id = 2;
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
154
|
+
expect(store.a.id).to.equal(2);
|
|
155
|
+
expect(store.b.id).to.equal(2);
|
|
156
|
+
expect(store.a.nested.id).to.equal(2);
|
|
157
|
+
expect(store.b.nested.id).to.equal(2);
|
|
160
158
|
store.b.id = 3;
|
|
161
159
|
store.b.nested.id = 3;
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
160
|
+
expect(store.b.id).to.equal(3);
|
|
161
|
+
expect(store.a.id).to.equal(3);
|
|
162
|
+
expect(store.a.nested.id).to.equal(3);
|
|
163
|
+
expect(store.b.nested.id).to.equal(3);
|
|
166
164
|
store.a.id = 4;
|
|
167
165
|
store.a.nested.id = 4;
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
166
|
+
expect(store.a.id).to.equal(4);
|
|
167
|
+
expect(store.b.id).to.equal(4);
|
|
168
|
+
expect(store.a.nested.id).to.equal(4);
|
|
169
|
+
expect(store.b.nested.id).to.equal(4);
|
|
172
170
|
});
|
|
173
|
-
|
|
171
|
+
it("should be able to reset values with Object.assign", () => {
|
|
174
172
|
const initialNested = { ...nested };
|
|
175
173
|
const initialState = { ...state, nested: initialNested };
|
|
176
174
|
store.a = 2;
|
|
177
175
|
store.nested.b = 3;
|
|
178
176
|
Object.assign(store, initialState);
|
|
179
|
-
|
|
180
|
-
|
|
177
|
+
expect(store.a).to.equal(1);
|
|
178
|
+
expect(store.nested.b).to.equal(2);
|
|
181
179
|
});
|
|
182
180
|
});
|
|
183
|
-
|
|
184
|
-
|
|
181
|
+
describe("delete", () => {
|
|
182
|
+
it("should delete properties before they are accessed", () => {
|
|
185
183
|
delete store.a;
|
|
186
|
-
|
|
184
|
+
expect(store.a).to.equal(undefined);
|
|
187
185
|
});
|
|
188
|
-
|
|
189
|
-
|
|
186
|
+
it("should delete properties after they are accessed", () => {
|
|
187
|
+
expect(store.a).to.equal(1);
|
|
190
188
|
delete store.a;
|
|
191
|
-
|
|
189
|
+
expect(store.a).to.equal(undefined);
|
|
192
190
|
});
|
|
193
|
-
|
|
191
|
+
it("should delete nested properties before they are accessed", () => {
|
|
194
192
|
delete store.nested.b;
|
|
195
|
-
|
|
193
|
+
expect(store.nested.b).to.equal(undefined);
|
|
196
194
|
});
|
|
197
|
-
|
|
198
|
-
|
|
195
|
+
it("should delete nested properties after they are accessed", () => {
|
|
196
|
+
expect(store.nested.b).to.equal(2);
|
|
199
197
|
delete store.nested.b;
|
|
200
|
-
|
|
198
|
+
expect(store.nested.b).to.equal(undefined);
|
|
201
199
|
});
|
|
202
|
-
|
|
200
|
+
it("should delete properties in arrays before they are accessed", () => {
|
|
203
201
|
delete store.array[0];
|
|
204
|
-
|
|
202
|
+
expect(store.array[0]).to.equal(undefined);
|
|
205
203
|
});
|
|
206
|
-
|
|
207
|
-
|
|
204
|
+
it("should delete properties in arrays after they are accessed", () => {
|
|
205
|
+
expect(store.array[0]).to.equal(3);
|
|
208
206
|
delete store.array[0];
|
|
209
|
-
|
|
207
|
+
expect(store.array[0]).to.equal(undefined);
|
|
210
208
|
});
|
|
211
209
|
});
|
|
212
|
-
|
|
213
|
-
|
|
210
|
+
describe("ownKeys", () => {
|
|
211
|
+
it("should return own properties in objects", () => {
|
|
214
212
|
const state = { a: 1, b: 2 };
|
|
215
|
-
const store =
|
|
213
|
+
const store = deepSignal(state);
|
|
216
214
|
let sum = 0;
|
|
217
215
|
for (const property in store) {
|
|
218
216
|
sum += store[property];
|
|
219
217
|
}
|
|
220
|
-
|
|
218
|
+
expect(sum).to.equal(3);
|
|
221
219
|
});
|
|
222
|
-
|
|
220
|
+
it("should return own properties in arrays", () => {
|
|
223
221
|
const state = [1, 2];
|
|
224
|
-
const store =
|
|
222
|
+
const store = deepSignal(state);
|
|
225
223
|
let sum = 0;
|
|
226
224
|
for (const property of store) {
|
|
227
225
|
sum += property;
|
|
228
226
|
}
|
|
229
|
-
|
|
227
|
+
expect(sum).to.equal(3);
|
|
230
228
|
});
|
|
231
|
-
|
|
229
|
+
it("should spread objects correctly", () => {
|
|
232
230
|
const store2 = { ...store };
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
231
|
+
expect(store2.a).to.equal(1);
|
|
232
|
+
expect(store2.nested.b).to.equal(2);
|
|
233
|
+
expect(store2.array[0]).to.equal(3);
|
|
234
|
+
expect(typeof store2.array[1] === "object" && store2.array[1].b).to.equal(2);
|
|
237
235
|
});
|
|
238
|
-
|
|
236
|
+
it("should spread arrays correctly", () => {
|
|
239
237
|
const array2 = [...store.array];
|
|
240
|
-
|
|
241
|
-
|
|
238
|
+
expect(array2[0]).to.equal(3);
|
|
239
|
+
expect(typeof array2[1] === "object" && array2[1].b).to.equal(2);
|
|
242
240
|
});
|
|
243
241
|
});
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
const store =
|
|
242
|
+
describe("computations", () => {
|
|
243
|
+
it("should subscribe to values mutated with setters", () => {
|
|
244
|
+
const store = deepSignal({
|
|
247
245
|
counter: 1,
|
|
248
246
|
get double() {
|
|
249
247
|
return store.counter * 2;
|
|
@@ -254,59 +252,59 @@ const __1 = require("../..");
|
|
|
254
252
|
});
|
|
255
253
|
let counter = 0;
|
|
256
254
|
let double = 0;
|
|
257
|
-
|
|
255
|
+
effect(() => {
|
|
258
256
|
counter = store.counter;
|
|
259
257
|
double = store.double;
|
|
260
258
|
});
|
|
261
|
-
|
|
262
|
-
|
|
259
|
+
expect(counter).to.equal(1);
|
|
260
|
+
expect(double).to.equal(2);
|
|
263
261
|
store.double = 4;
|
|
264
|
-
|
|
265
|
-
|
|
262
|
+
expect(counter).to.equal(2);
|
|
263
|
+
expect(double).to.equal(4);
|
|
266
264
|
});
|
|
267
|
-
|
|
268
|
-
const store =
|
|
265
|
+
it("should subscribe to changes when an item is removed from the array", () => {
|
|
266
|
+
const store = deepSignal([0, 0, 0]);
|
|
269
267
|
let sum = 0;
|
|
270
|
-
|
|
268
|
+
effect(() => {
|
|
271
269
|
sum = 0;
|
|
272
270
|
sum = store.reduce((sum) => sum + 1, 0);
|
|
273
271
|
});
|
|
274
|
-
|
|
272
|
+
expect(sum).to.equal(3);
|
|
275
273
|
store.splice(2, 1);
|
|
276
|
-
|
|
274
|
+
expect(sum).to.equal(2);
|
|
277
275
|
});
|
|
278
|
-
|
|
276
|
+
it("should subscribe to changes to for..in loops", () => {
|
|
279
277
|
const state = { a: 0, b: 0 };
|
|
280
|
-
const store =
|
|
278
|
+
const store = deepSignal(state);
|
|
281
279
|
let sum = 0;
|
|
282
|
-
|
|
280
|
+
effect(() => {
|
|
283
281
|
sum = 0;
|
|
284
282
|
for (const _ in store) {
|
|
285
283
|
sum += 1;
|
|
286
284
|
}
|
|
287
285
|
});
|
|
288
|
-
|
|
286
|
+
expect(sum).to.equal(2);
|
|
289
287
|
store.c = 0;
|
|
290
|
-
|
|
288
|
+
expect(sum).to.equal(3);
|
|
291
289
|
delete store.c;
|
|
292
|
-
|
|
290
|
+
expect(sum).to.equal(2);
|
|
293
291
|
});
|
|
294
|
-
|
|
295
|
-
const store =
|
|
292
|
+
it("should not retrigger effects when unrelated object branches change", () => {
|
|
293
|
+
const store = deepSignal({
|
|
296
294
|
alpha: { value: 1 },
|
|
297
295
|
beta: { value: 2 },
|
|
298
296
|
});
|
|
299
297
|
let runs = 0;
|
|
300
|
-
|
|
298
|
+
effect(() => {
|
|
301
299
|
runs += 1;
|
|
302
300
|
store.alpha.value;
|
|
303
301
|
});
|
|
304
|
-
|
|
302
|
+
expect(runs).to.equal(1);
|
|
305
303
|
store.beta.value = 3;
|
|
306
|
-
|
|
304
|
+
expect(runs).to.equal(1);
|
|
307
305
|
});
|
|
308
|
-
|
|
309
|
-
const store =
|
|
306
|
+
it("should not retrigger effects for untouched Set entries", () => {
|
|
307
|
+
const store = deepSignal({
|
|
310
308
|
set: new Set([
|
|
311
309
|
{ id: "a", data: { value: 1 } },
|
|
312
310
|
{ id: "b", data: { value: 2 } },
|
|
@@ -317,201 +315,201 @@ const __1 = require("../..");
|
|
|
317
315
|
});
|
|
318
316
|
const [entryA, entryB] = Array.from(store.set);
|
|
319
317
|
let runs = 0;
|
|
320
|
-
|
|
318
|
+
effect(() => {
|
|
321
319
|
runs += 1;
|
|
322
320
|
entryA.data.value;
|
|
323
321
|
});
|
|
324
|
-
|
|
322
|
+
expect(runs).to.equal(1);
|
|
325
323
|
entryB.data.value = 5;
|
|
326
|
-
|
|
324
|
+
expect(runs).to.equal(1);
|
|
327
325
|
});
|
|
328
|
-
|
|
329
|
-
const store =
|
|
326
|
+
it("should subscribe to array iteration via Symbol.iterator", () => {
|
|
327
|
+
const store = deepSignal([1, 2]);
|
|
330
328
|
let total = 0;
|
|
331
|
-
|
|
329
|
+
effect(() => {
|
|
332
330
|
total = 0;
|
|
333
331
|
for (const value of store) {
|
|
334
332
|
total += value;
|
|
335
333
|
}
|
|
336
334
|
});
|
|
337
|
-
|
|
335
|
+
expect(total).to.equal(3);
|
|
338
336
|
store.push(3);
|
|
339
|
-
|
|
337
|
+
expect(total).to.equal(6);
|
|
340
338
|
});
|
|
341
|
-
|
|
342
|
-
const store =
|
|
339
|
+
it("should subscribe to Set iteration via Symbol.iterator", () => {
|
|
340
|
+
const store = deepSignal({ set: new Set([1, 2]) });
|
|
343
341
|
let total = 0;
|
|
344
|
-
|
|
342
|
+
effect(() => {
|
|
345
343
|
total = 0;
|
|
346
344
|
for (const value of store.set) {
|
|
347
345
|
total += value;
|
|
348
346
|
}
|
|
349
347
|
});
|
|
350
|
-
|
|
348
|
+
expect(total).to.equal(3);
|
|
351
349
|
store.set.add(3);
|
|
352
|
-
|
|
350
|
+
expect(total).to.equal(6);
|
|
353
351
|
store.set.delete(1);
|
|
354
|
-
|
|
352
|
+
expect(total).to.equal(5);
|
|
355
353
|
});
|
|
356
|
-
|
|
357
|
-
const store =
|
|
354
|
+
it("should subscribe when using Set iterator helper chains", () => {
|
|
355
|
+
const store = deepSignal({ set: new Set([1]) });
|
|
358
356
|
let reduced = 0;
|
|
359
|
-
|
|
357
|
+
effect(() => {
|
|
360
358
|
reduced = store.set
|
|
361
359
|
.map((value) => value)
|
|
362
360
|
.reduce((acc, value) => acc + value, 0);
|
|
363
361
|
});
|
|
364
|
-
|
|
362
|
+
expect(reduced).to.equal(1);
|
|
365
363
|
store.set.add(2);
|
|
366
|
-
|
|
364
|
+
expect(reduced).to.equal(3);
|
|
367
365
|
store.set.delete(1);
|
|
368
|
-
|
|
366
|
+
expect(reduced).to.equal(2);
|
|
369
367
|
});
|
|
370
|
-
|
|
368
|
+
it("should subscribe to changes for Object.getOwnPropertyNames()", () => {
|
|
371
369
|
const state = { a: 1, b: 2 };
|
|
372
|
-
const store =
|
|
370
|
+
const store = deepSignal(state);
|
|
373
371
|
let sum = 0;
|
|
374
|
-
|
|
372
|
+
effect(() => {
|
|
375
373
|
sum = 0;
|
|
376
374
|
const keys = Object.getOwnPropertyNames(store);
|
|
377
375
|
for (const _ of keys) {
|
|
378
376
|
sum += 1;
|
|
379
377
|
}
|
|
380
378
|
});
|
|
381
|
-
|
|
379
|
+
expect(sum).to.equal(2);
|
|
382
380
|
store.c = 0;
|
|
383
|
-
|
|
381
|
+
expect(sum).to.equal(3);
|
|
384
382
|
delete store.a;
|
|
385
|
-
|
|
383
|
+
expect(sum).to.equal(2);
|
|
386
384
|
});
|
|
387
|
-
|
|
385
|
+
it("should subscribe to changes to Object.keys/values/entries()", () => {
|
|
388
386
|
const state = { a: 1, b: 2 };
|
|
389
|
-
const store =
|
|
387
|
+
const store = deepSignal(state);
|
|
390
388
|
let keys = 0;
|
|
391
389
|
let values = 0;
|
|
392
390
|
let entries = 0;
|
|
393
|
-
|
|
391
|
+
effect(() => {
|
|
394
392
|
keys = 0;
|
|
395
393
|
Object.keys(store).forEach(() => (keys += 1));
|
|
396
394
|
});
|
|
397
|
-
|
|
395
|
+
effect(() => {
|
|
398
396
|
values = 0;
|
|
399
397
|
Object.values(store).forEach(() => (values += 1));
|
|
400
398
|
});
|
|
401
|
-
|
|
399
|
+
effect(() => {
|
|
402
400
|
entries = 0;
|
|
403
401
|
Object.entries(store).forEach(() => (entries += 1));
|
|
404
402
|
});
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
403
|
+
expect(keys).to.equal(2);
|
|
404
|
+
expect(values).to.equal(2);
|
|
405
|
+
expect(entries).to.equal(2);
|
|
408
406
|
store.c = 0;
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
407
|
+
expect(keys).to.equal(3);
|
|
408
|
+
expect(values).to.equal(3);
|
|
409
|
+
expect(entries).to.equal(3);
|
|
412
410
|
delete store.a;
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
411
|
+
expect(keys).to.equal(2);
|
|
412
|
+
expect(values).to.equal(2);
|
|
413
|
+
expect(entries).to.equal(2);
|
|
416
414
|
});
|
|
417
|
-
|
|
418
|
-
const store =
|
|
415
|
+
it("should subscribe to changes to for..of loops", () => {
|
|
416
|
+
const store = deepSignal([0, 0]);
|
|
419
417
|
let sum = 0;
|
|
420
|
-
|
|
418
|
+
effect(() => {
|
|
421
419
|
sum = 0;
|
|
422
420
|
for (const _ of store) {
|
|
423
421
|
sum += 1;
|
|
424
422
|
}
|
|
425
423
|
});
|
|
426
|
-
|
|
424
|
+
expect(sum).to.equal(2);
|
|
427
425
|
store.push(0);
|
|
428
|
-
|
|
426
|
+
expect(sum).to.equal(3);
|
|
429
427
|
store.splice(0, 1);
|
|
430
|
-
|
|
428
|
+
expect(sum).to.equal(2);
|
|
431
429
|
});
|
|
432
|
-
|
|
433
|
-
const store =
|
|
430
|
+
it("should subscribe to implicit changes in array items", () => {
|
|
431
|
+
const store = deepSignal(["foo", "bar"]);
|
|
434
432
|
let x = "";
|
|
435
|
-
|
|
433
|
+
effect(() => {
|
|
436
434
|
x = store.join(" ");
|
|
437
435
|
});
|
|
438
|
-
|
|
436
|
+
expect(x).to.equal("foo bar");
|
|
439
437
|
store.push("baz");
|
|
440
|
-
|
|
438
|
+
expect(x).to.equal("foo bar baz");
|
|
441
439
|
store.splice(0, 1);
|
|
442
|
-
|
|
440
|
+
expect(x).to.equal("bar baz");
|
|
443
441
|
store.splice(1, 1, "bam");
|
|
444
|
-
|
|
442
|
+
expect(x).to.equal("bar bam");
|
|
445
443
|
});
|
|
446
|
-
|
|
444
|
+
it("should subscribe to changes when deleting properties", () => {
|
|
447
445
|
let x, y;
|
|
448
|
-
|
|
446
|
+
effect(() => {
|
|
449
447
|
x = store.a;
|
|
450
448
|
});
|
|
451
|
-
|
|
449
|
+
effect(() => {
|
|
452
450
|
y = store.nested.b;
|
|
453
451
|
});
|
|
454
|
-
|
|
452
|
+
expect(x).to.equal(1);
|
|
455
453
|
delete store.a;
|
|
456
|
-
|
|
457
|
-
|
|
454
|
+
expect(x).to.equal(undefined);
|
|
455
|
+
expect(y).to.equal(2);
|
|
458
456
|
delete store.nested.b;
|
|
459
|
-
|
|
457
|
+
expect(y).to.equal(undefined);
|
|
460
458
|
});
|
|
461
|
-
|
|
459
|
+
it("should subscribe to changes when mutating objects", () => {
|
|
462
460
|
let x, y;
|
|
463
|
-
const store =
|
|
461
|
+
const store = deepSignal({
|
|
464
462
|
b: [
|
|
465
463
|
{ id: 1, nested: { id: 1 } },
|
|
466
464
|
{ id: 2, nested: { id: 2 } },
|
|
467
465
|
],
|
|
468
466
|
});
|
|
469
|
-
|
|
467
|
+
effect(() => {
|
|
470
468
|
x = store.a?.id;
|
|
471
469
|
});
|
|
472
|
-
|
|
470
|
+
effect(() => {
|
|
473
471
|
y = store.a?.nested.id;
|
|
474
472
|
});
|
|
475
|
-
|
|
476
|
-
|
|
473
|
+
expect(x).to.equal(undefined);
|
|
474
|
+
expect(y).to.equal(undefined);
|
|
477
475
|
store.a = store.b[0];
|
|
478
|
-
|
|
479
|
-
|
|
476
|
+
expect(x).to.equal(1);
|
|
477
|
+
expect(y).to.equal(1);
|
|
480
478
|
store.a = store.b[1];
|
|
481
|
-
|
|
482
|
-
|
|
479
|
+
expect(x).to.equal(2);
|
|
480
|
+
expect(y).to.equal(2);
|
|
483
481
|
store.a = undefined;
|
|
484
|
-
|
|
485
|
-
|
|
482
|
+
expect(x).to.equal(undefined);
|
|
483
|
+
expect(y).to.equal(undefined);
|
|
486
484
|
store.a = store.b[1];
|
|
487
|
-
|
|
488
|
-
|
|
485
|
+
expect(x).to.equal(2);
|
|
486
|
+
expect(y).to.equal(2);
|
|
489
487
|
});
|
|
490
|
-
|
|
488
|
+
it("should trigger effects after mutations happen", () => {
|
|
491
489
|
let x;
|
|
492
|
-
|
|
490
|
+
effect(() => {
|
|
493
491
|
x = store.a;
|
|
494
492
|
});
|
|
495
|
-
|
|
493
|
+
expect(x).to.equal(1);
|
|
496
494
|
store.a = 11;
|
|
497
|
-
|
|
495
|
+
expect(x).to.equal(11);
|
|
498
496
|
});
|
|
499
|
-
|
|
497
|
+
it("should subscribe corretcly from getters", () => {
|
|
500
498
|
let x;
|
|
501
|
-
const store =
|
|
499
|
+
const store = deepSignal({
|
|
502
500
|
counter: 1,
|
|
503
501
|
get double() {
|
|
504
502
|
return store.counter * 2;
|
|
505
503
|
},
|
|
506
504
|
});
|
|
507
|
-
|
|
508
|
-
|
|
505
|
+
effect(() => (x = store.double));
|
|
506
|
+
expect(x).to.equal(2);
|
|
509
507
|
store.counter = 2;
|
|
510
|
-
|
|
508
|
+
expect(x).to.equal(4);
|
|
511
509
|
});
|
|
512
|
-
|
|
510
|
+
it("should subscribe corretcly from getters returning other parts of the store", () => {
|
|
513
511
|
let data;
|
|
514
|
-
const store =
|
|
512
|
+
const store = deepSignal({
|
|
515
513
|
switch: "a",
|
|
516
514
|
a: { data: "a" },
|
|
517
515
|
b: { data: "b" },
|
|
@@ -519,33 +517,33 @@ const __1 = require("../..");
|
|
|
519
517
|
return store.switch === "a" ? store.a : store.b;
|
|
520
518
|
},
|
|
521
519
|
});
|
|
522
|
-
|
|
523
|
-
|
|
520
|
+
effect(() => (data = store.aOrB.data));
|
|
521
|
+
expect(data).to.equal("a");
|
|
524
522
|
store.switch = "b";
|
|
525
|
-
|
|
523
|
+
expect(data).to.equal("b");
|
|
526
524
|
});
|
|
527
|
-
|
|
525
|
+
it("should be able to reset values with Object.assign and still react to changes", () => {
|
|
528
526
|
const initialNested = { ...nested };
|
|
529
527
|
const initialState = { ...state, nested: initialNested };
|
|
530
528
|
let a, b;
|
|
531
|
-
|
|
529
|
+
effect(() => {
|
|
532
530
|
a = store.a;
|
|
533
531
|
});
|
|
534
|
-
|
|
532
|
+
effect(() => {
|
|
535
533
|
b = store.nested.b;
|
|
536
534
|
});
|
|
537
535
|
store.a = 2;
|
|
538
536
|
store.nested.b = 3;
|
|
539
|
-
|
|
540
|
-
|
|
537
|
+
expect(a).to.equal(2);
|
|
538
|
+
expect(b).to.equal(3);
|
|
541
539
|
Object.assign(store, initialState);
|
|
542
|
-
|
|
543
|
-
|
|
540
|
+
expect(a).to.equal(1);
|
|
541
|
+
expect(b).to.equal(2);
|
|
544
542
|
});
|
|
545
543
|
});
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
const signalObj =
|
|
544
|
+
describe("refs", () => {
|
|
545
|
+
it("should change if children changed when replaceProxiesInBranchOnChange", async () => {
|
|
546
|
+
const signalObj = deepSignal({
|
|
549
547
|
primitive: 1,
|
|
550
548
|
nestedObject: { primitive: 2 },
|
|
551
549
|
nestedSetOfPrimitives: new Set([1, 2, "three"]),
|
|
@@ -570,251 +568,251 @@ const __1 = require("../..");
|
|
|
570
568
|
let [naoo1, naoo2] = signalObj.nestedArrayOfObjects;
|
|
571
569
|
// Mutate root primitive - should not affect nested proxies
|
|
572
570
|
signalObj.primitive = 2;
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
571
|
+
expect(signalObj.nestedObject).toBe(no);
|
|
572
|
+
expect(signalObj.nestedObject.primitive).toBe(nop);
|
|
573
|
+
expect(signalObj.nestedSetOfPrimitives).toBe(nsop);
|
|
574
|
+
expect(signalObj.nestedSetOfObjects).toBe(nsoo);
|
|
575
|
+
expect(signalObj.nestedArrayOfPrimitives).toBe(naop);
|
|
576
|
+
expect(signalObj.nestedArrayOfObjects).toBe(naoo);
|
|
579
577
|
// Mutate nested object primitive - should replace nestedObject proxy
|
|
580
578
|
signalObj.nestedObject.primitive = 3;
|
|
581
|
-
|
|
582
|
-
|
|
579
|
+
expect(signalObj.nestedObject.primitive).toBe(3);
|
|
580
|
+
expect(signalObj.nestedObject).not.toBe(no);
|
|
583
581
|
no = signalObj.nestedObject;
|
|
584
582
|
// Unrelated proxies should remain the same
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
583
|
+
expect(signalObj.nestedSetOfPrimitives).toBe(nsop);
|
|
584
|
+
expect(signalObj.nestedSetOfObjects).toBe(nsoo);
|
|
585
|
+
expect(signalObj.nestedArrayOfPrimitives).toBe(naop);
|
|
586
|
+
expect(signalObj.nestedArrayOfObjects).toBe(naoo);
|
|
589
587
|
// Mutate Set of primitives - should replace the Set proxy
|
|
590
588
|
signalObj.nestedSetOfPrimitives.add(4);
|
|
591
|
-
|
|
589
|
+
expect(signalObj.nestedSetOfPrimitives).not.toBe(nsop);
|
|
592
590
|
nsop = signalObj.nestedSetOfPrimitives;
|
|
593
|
-
|
|
591
|
+
expect(signalObj.nestedSetOfPrimitives.has(4)).toBe(true);
|
|
594
592
|
// Unrelated proxies should remain the same
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
593
|
+
expect(signalObj.nestedObject).toBe(no);
|
|
594
|
+
expect(signalObj.nestedSetOfObjects).toBe(nsoo);
|
|
595
|
+
expect(signalObj.nestedArrayOfPrimitives).toBe(naop);
|
|
596
|
+
expect(signalObj.nestedArrayOfObjects).toBe(naoo);
|
|
599
597
|
// Mutate object inside Set - should replace Set proxy and the object proxy
|
|
600
598
|
nsoo1.primitive = false;
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
599
|
+
expect([...signalObj.nestedSetOfObjects][1]).toBe(nsoo2);
|
|
600
|
+
expect([...signalObj.nestedSetOfObjects][0]).not.toBe(nsoo1);
|
|
601
|
+
expect(signalObj.nestedSetOfObjects).not.toBe(nsoo);
|
|
604
602
|
nsoo = signalObj.nestedSetOfObjects;
|
|
605
603
|
[nsoo1, nsoo2] = [...signalObj.nestedSetOfObjects];
|
|
606
604
|
// Unrelated proxies should remain the same
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
605
|
+
expect(signalObj.nestedObject).toBe(no);
|
|
606
|
+
expect(signalObj.nestedSetOfPrimitives).toBe(nsop);
|
|
607
|
+
expect(signalObj.nestedArrayOfPrimitives).toBe(naop);
|
|
608
|
+
expect(signalObj.nestedArrayOfObjects).toBe(naoo);
|
|
611
609
|
// Mutate array of primitives - should replace the array proxy
|
|
612
610
|
signalObj.nestedArrayOfPrimitives.push(4);
|
|
613
|
-
|
|
611
|
+
expect(signalObj.nestedArrayOfPrimitives).not.toBe(naop);
|
|
614
612
|
naop = signalObj.nestedArrayOfPrimitives;
|
|
615
|
-
|
|
613
|
+
expect(signalObj.nestedArrayOfPrimitives.length).toBe(4);
|
|
616
614
|
// Unrelated proxies should remain the same
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
615
|
+
expect(signalObj.nestedObject).toBe(no);
|
|
616
|
+
expect(signalObj.nestedSetOfPrimitives).toBe(nsop);
|
|
617
|
+
expect(signalObj.nestedSetOfObjects).toBe(nsoo);
|
|
618
|
+
expect(signalObj.nestedArrayOfObjects).toBe(naoo);
|
|
621
619
|
// Mutate object inside array - should replace array proxy and the object proxy
|
|
622
620
|
naoo1.primitive = false;
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
621
|
+
expect(signalObj.nestedArrayOfObjects[0]).not.toBe(naoo1);
|
|
622
|
+
expect(signalObj.nestedArrayOfObjects[1]).toBe(naoo2);
|
|
623
|
+
expect(signalObj.nestedArrayOfObjects).not.toBe(naoo);
|
|
626
624
|
naoo = signalObj.nestedArrayOfObjects;
|
|
627
625
|
[naoo1, naoo2] = signalObj.nestedArrayOfObjects;
|
|
628
626
|
// Unrelated proxies should remain the same
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
627
|
+
expect(signalObj.nestedObject).toBe(no);
|
|
628
|
+
expect(signalObj.nestedSetOfPrimitives).toBe(nsop);
|
|
629
|
+
expect(signalObj.nestedSetOfObjects).toBe(nsoo);
|
|
630
|
+
expect(signalObj.nestedArrayOfPrimitives).toBe(naop);
|
|
633
631
|
});
|
|
634
|
-
|
|
632
|
+
it("should return the same proxy if initialized more than once", () => {
|
|
635
633
|
const state = {};
|
|
636
|
-
const store1 =
|
|
637
|
-
const store2 =
|
|
638
|
-
|
|
634
|
+
const store1 = deepSignal(state);
|
|
635
|
+
const store2 = deepSignal(state);
|
|
636
|
+
expect(store1).to.equal(store2);
|
|
639
637
|
});
|
|
640
638
|
});
|
|
641
|
-
|
|
642
|
-
|
|
639
|
+
describe("unsupported data structures", () => {
|
|
640
|
+
it("should throw when trying to deepsignal a class instance", () => {
|
|
643
641
|
class MyClass {
|
|
644
642
|
}
|
|
645
643
|
const obj = new MyClass();
|
|
646
|
-
|
|
644
|
+
expect(() => deepSignal(obj)).to.throw();
|
|
647
645
|
});
|
|
648
|
-
|
|
646
|
+
it("should not wrap a class instance", () => {
|
|
649
647
|
class MyClass {
|
|
650
648
|
}
|
|
651
649
|
const obj = new MyClass();
|
|
652
|
-
const store =
|
|
653
|
-
|
|
650
|
+
const store = deepSignal({ obj });
|
|
651
|
+
expect(store.obj).to.equal(obj);
|
|
654
652
|
});
|
|
655
|
-
|
|
653
|
+
it("should not wrap built-ins in proxies", () => {
|
|
656
654
|
window.MyClass = class MyClass {
|
|
657
655
|
};
|
|
658
656
|
const obj = new window.MyClass();
|
|
659
|
-
const store =
|
|
660
|
-
|
|
657
|
+
const store = deepSignal({ obj });
|
|
658
|
+
expect(store.obj).to.equal(obj);
|
|
661
659
|
});
|
|
662
660
|
// it("should not wrap elements in proxies", () => {
|
|
663
661
|
// const el = window.document.createElement("div");
|
|
664
662
|
// const store = deepSignal({ el });
|
|
665
663
|
// expect(store.el).to.equal(el);
|
|
666
664
|
// });
|
|
667
|
-
|
|
665
|
+
it("should wrap global objects", () => {
|
|
668
666
|
window.obj = { b: 2 };
|
|
669
|
-
const store =
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
667
|
+
const store = deepSignal(window.obj);
|
|
668
|
+
expect(store).to.not.equal(window.obj);
|
|
669
|
+
expect(store).to.deep.equal({ b: 2 });
|
|
670
|
+
expect(store.b).to.equal(2);
|
|
673
671
|
});
|
|
674
|
-
|
|
672
|
+
it("should not wrap dates", () => {
|
|
675
673
|
const date = new Date();
|
|
676
|
-
const store =
|
|
677
|
-
|
|
674
|
+
const store = deepSignal({ date });
|
|
675
|
+
expect(store.date).to.equal(date);
|
|
678
676
|
});
|
|
679
|
-
|
|
677
|
+
it("should not wrap regular expressions", () => {
|
|
680
678
|
const regex = new RegExp("");
|
|
681
|
-
const store =
|
|
682
|
-
|
|
679
|
+
const store = deepSignal({ regex });
|
|
680
|
+
expect(store.regex).to.equal(regex);
|
|
683
681
|
});
|
|
684
|
-
|
|
682
|
+
it("should not wrap Map", () => {
|
|
685
683
|
const map = new Map();
|
|
686
|
-
const store =
|
|
687
|
-
|
|
684
|
+
const store = deepSignal({ map });
|
|
685
|
+
expect(store.map).to.equal(map);
|
|
688
686
|
});
|
|
689
|
-
|
|
687
|
+
it("should wrap Set and emit patches on structural changes", () => {
|
|
690
688
|
const set = new Set([1]);
|
|
691
|
-
const store =
|
|
689
|
+
const store = deepSignal({ set });
|
|
692
690
|
// The Set itself should be proxied (different reference)
|
|
693
|
-
|
|
691
|
+
expect(store.set).to.not.equal(set);
|
|
694
692
|
// Size observable via manual mutation + patch emission (indirectly validated in watchPatches Set test)
|
|
695
693
|
store.set.add(2);
|
|
696
694
|
store.set.delete(1);
|
|
697
|
-
|
|
695
|
+
expect(store.set.has(2)).to.equal(true);
|
|
698
696
|
});
|
|
699
|
-
|
|
700
|
-
const store =
|
|
697
|
+
it("should expose reactive Set size without throwing", () => {
|
|
698
|
+
const store = deepSignal({ set: new Set([1, 2]) });
|
|
701
699
|
let size = 0;
|
|
702
|
-
|
|
700
|
+
effect(() => {
|
|
703
701
|
size = store.set.size;
|
|
704
702
|
});
|
|
705
|
-
|
|
706
|
-
|
|
703
|
+
expect(store.set.size).to.equal(2);
|
|
704
|
+
expect(size).to.equal(2);
|
|
707
705
|
store.set.add(3);
|
|
708
|
-
|
|
709
|
-
|
|
706
|
+
expect(store.set.size).to.equal(3);
|
|
707
|
+
expect(size).to.equal(3);
|
|
710
708
|
store.set.delete(1);
|
|
711
|
-
|
|
712
|
-
|
|
709
|
+
expect(store.set.size).to.equal(2);
|
|
710
|
+
expect(size).to.equal(2);
|
|
713
711
|
});
|
|
714
712
|
});
|
|
715
|
-
|
|
716
|
-
|
|
713
|
+
describe("symbols", () => {
|
|
714
|
+
it("should observe symbols", () => {
|
|
717
715
|
const key = Symbol("key");
|
|
718
716
|
let x;
|
|
719
|
-
const store =
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
717
|
+
const store = deepSignal({});
|
|
718
|
+
effect(() => (x = store[key]));
|
|
719
|
+
expect(store[key]).to.equal(undefined);
|
|
720
|
+
expect(x).to.equal(undefined);
|
|
723
721
|
store[key] = true;
|
|
724
|
-
|
|
725
|
-
|
|
722
|
+
expect(store[key]).to.equal(true);
|
|
723
|
+
expect(x).to.equal(true);
|
|
726
724
|
});
|
|
727
|
-
|
|
725
|
+
it("should not observe well-known symbols", () => {
|
|
728
726
|
const key = Symbol.isConcatSpreadable;
|
|
729
727
|
let x;
|
|
730
|
-
const state =
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
728
|
+
const state = deepSignal({});
|
|
729
|
+
effect(() => (x = state[key]));
|
|
730
|
+
expect(state[key]).to.equal(undefined);
|
|
731
|
+
expect(x).to.equal(undefined);
|
|
734
732
|
state[key] = true;
|
|
735
|
-
|
|
736
|
-
|
|
733
|
+
expect(state[key]).to.equal(true);
|
|
734
|
+
expect(x).to.equal(undefined);
|
|
737
735
|
});
|
|
738
|
-
|
|
736
|
+
it("access well-known symbol property returns raw value and not a signal", () => {
|
|
739
737
|
const tag = Symbol.toStringTag;
|
|
740
|
-
const ds =
|
|
738
|
+
const ds = deepSignal({ [tag]: "Custom", x: 1 });
|
|
741
739
|
const val = ds[tag];
|
|
742
|
-
|
|
740
|
+
expect(val).toBe("Custom");
|
|
743
741
|
});
|
|
744
|
-
|
|
745
|
-
const ds =
|
|
742
|
+
it("access Set Symbol.iterator.toString() key path (skip branch)", () => {
|
|
743
|
+
const ds = deepSignal({ set: new Set([1]) });
|
|
746
744
|
const iterKey = Symbol.iterator.toString(); // 'Symbol(Symbol.iterator)'
|
|
747
745
|
// Accessing this string property triggers skip branch (no special handling needed)
|
|
748
746
|
const maybe = ds.set[iterKey];
|
|
749
747
|
// underlying Set likely has undefined for that string key
|
|
750
|
-
|
|
748
|
+
expect(maybe).toBeUndefined();
|
|
751
749
|
});
|
|
752
750
|
});
|
|
753
|
-
|
|
754
|
-
|
|
751
|
+
describe("shallow", () => {
|
|
752
|
+
it("should not proxy shallow objects", () => {
|
|
755
753
|
const shallowObj1 = { a: 1 };
|
|
756
754
|
let shallowObj2 = { b: 2 };
|
|
757
755
|
const deepObj = { c: 3 };
|
|
758
|
-
shallowObj2 =
|
|
759
|
-
const store =
|
|
760
|
-
shallowObj1:
|
|
756
|
+
shallowObj2 = shallow(shallowObj2);
|
|
757
|
+
const store = deepSignal({
|
|
758
|
+
shallowObj1: shallow(shallowObj1),
|
|
761
759
|
shallowObj2,
|
|
762
760
|
deepObj,
|
|
763
761
|
});
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
762
|
+
expect(store.shallowObj1.a).to.equal(1);
|
|
763
|
+
expect(store.shallowObj2.b).to.equal(2);
|
|
764
|
+
expect(store.deepObj.c).to.equal(3);
|
|
765
|
+
expect(store.shallowObj1).to.equal(shallowObj1);
|
|
766
|
+
expect(store.shallowObj2).to.equal(shallowObj2);
|
|
767
|
+
expect(store.deepObj).to.not.equal(deepObj);
|
|
770
768
|
});
|
|
771
|
-
|
|
769
|
+
it("should not proxy shallow objects if shallow is called on the reference before accessing the property", () => {
|
|
772
770
|
const shallowObj = { a: 1 };
|
|
773
771
|
const deepObj = { c: 3 };
|
|
774
|
-
const store =
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
});
|
|
781
|
-
|
|
772
|
+
const store = deepSignal({ shallowObj, deepObj });
|
|
773
|
+
shallow(shallowObj);
|
|
774
|
+
expect(store.shallowObj.a).to.equal(1);
|
|
775
|
+
expect(store.deepObj.c).to.equal(3);
|
|
776
|
+
expect(store.shallowObj).to.equal(shallowObj);
|
|
777
|
+
expect(store.deepObj).to.not.equal(deepObj);
|
|
778
|
+
});
|
|
779
|
+
it("should observe changes in the shallow object if the reference changes", () => {
|
|
782
780
|
const obj = { a: 1 };
|
|
783
|
-
const shallowObj =
|
|
784
|
-
const store =
|
|
781
|
+
const shallowObj = shallow(obj);
|
|
782
|
+
const store = deepSignal({ shallowObj });
|
|
785
783
|
let x;
|
|
786
|
-
|
|
784
|
+
effect(() => {
|
|
787
785
|
x = store.shallowObj.a;
|
|
788
786
|
});
|
|
789
|
-
|
|
790
|
-
store.shallowObj =
|
|
791
|
-
|
|
787
|
+
expect(x).to.equal(1);
|
|
788
|
+
store.shallowObj = shallow({ a: 2 });
|
|
789
|
+
expect(x).to.equal(2);
|
|
792
790
|
});
|
|
793
|
-
|
|
791
|
+
it("should stop observing changes in the shallow object if the reference changes and it's not shallow anymore", () => {
|
|
794
792
|
const obj = { a: 1 };
|
|
795
|
-
const shallowObj =
|
|
796
|
-
const store =
|
|
793
|
+
const shallowObj = shallow(obj);
|
|
794
|
+
const store = deepSignal({ obj: shallowObj });
|
|
797
795
|
let x;
|
|
798
|
-
|
|
796
|
+
effect(() => {
|
|
799
797
|
x = store.obj.a;
|
|
800
798
|
});
|
|
801
|
-
|
|
799
|
+
expect(x).to.equal(1);
|
|
802
800
|
store.obj = { a: 2 };
|
|
803
|
-
|
|
801
|
+
expect(x).to.equal(2);
|
|
804
802
|
store.obj.a = 3;
|
|
805
|
-
|
|
803
|
+
expect(x).to.equal(3);
|
|
806
804
|
});
|
|
807
|
-
|
|
805
|
+
it("should not observe changes in the props of the shallow object", () => {
|
|
808
806
|
const obj = { a: 1 };
|
|
809
|
-
const shallowObj =
|
|
810
|
-
const store =
|
|
807
|
+
const shallowObj = shallow(obj);
|
|
808
|
+
const store = deepSignal({ shallowObj });
|
|
811
809
|
let x;
|
|
812
|
-
|
|
810
|
+
effect(() => {
|
|
813
811
|
x = store.shallowObj.a;
|
|
814
812
|
});
|
|
815
|
-
|
|
813
|
+
expect(x).to.equal(1);
|
|
816
814
|
store.shallowObj.a = 2;
|
|
817
|
-
|
|
815
|
+
expect(x).to.equal(1);
|
|
818
816
|
});
|
|
819
817
|
});
|
|
820
818
|
});
|