@solidjs/signals 0.9.2 → 0.9.3
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/dev.js +135 -50
- package/dist/node.cjs +509 -426
- package/dist/prod.js +130 -45
- package/dist/types/core/constants.d.ts +1 -0
- package/dist/types/core/core.d.ts +4 -2
- package/dist/types/core/index.d.ts +1 -1
- package/dist/types/core/scheduler.d.ts +5 -3
- package/dist/types/index.d.ts +1 -1
- package/dist/types/store/projection.d.ts +8 -3
- package/dist/types/store/store.d.ts +10 -6
- package/package.json +3 -3
package/dist/dev.js
CHANGED
|
@@ -34,6 +34,7 @@ const EFFECT_USER = 2;
|
|
|
34
34
|
const NOT_PENDING = {};
|
|
35
35
|
const SUPPORTS_PROXY = typeof Proxy === "function";
|
|
36
36
|
const defaultContext = {};
|
|
37
|
+
const $REFRESH = Symbol("refresh");
|
|
37
38
|
function actualInsertIntoHeap(n, heap) {
|
|
38
39
|
const parentHeight =
|
|
39
40
|
(n._parent?._root ? n._parent._parentComputed?._height : n._parent?._height) ?? -1;
|
|
@@ -141,7 +142,7 @@ let scheduled = false;
|
|
|
141
142
|
function schedule() {
|
|
142
143
|
if (scheduled) return;
|
|
143
144
|
scheduled = true;
|
|
144
|
-
if (!globalQueue._running) queueMicrotask(flush);
|
|
145
|
+
if (!globalQueue._running) Promise.resolve().then(() => queueMicrotask(flush));
|
|
145
146
|
}
|
|
146
147
|
class Queue {
|
|
147
148
|
_parent = null;
|
|
@@ -226,6 +227,8 @@ class GlobalQueue extends Queue {
|
|
|
226
227
|
return;
|
|
227
228
|
}
|
|
228
229
|
this._pendingNodes.push(...activeTransition.pendingNodes);
|
|
230
|
+
this._optimisticNodes !== activeTransition.optimisticNodes &&
|
|
231
|
+
this._optimisticNodes.push(...activeTransition.optimisticNodes);
|
|
229
232
|
this.restoreQueues(activeTransition.queueStash);
|
|
230
233
|
transitions.delete(activeTransition);
|
|
231
234
|
activeTransition = null;
|
|
@@ -255,11 +258,12 @@ class GlobalQueue extends Queue {
|
|
|
255
258
|
initTransition(node) {
|
|
256
259
|
if (activeTransition && activeTransition.time === clock) return;
|
|
257
260
|
if (!activeTransition) {
|
|
258
|
-
activeTransition = node
|
|
261
|
+
activeTransition = node?._transition ?? {
|
|
259
262
|
time: clock,
|
|
260
263
|
pendingNodes: [],
|
|
261
264
|
asyncNodes: [],
|
|
262
265
|
optimisticNodes: [],
|
|
266
|
+
actions: [],
|
|
263
267
|
queueStash: { _queues: [[], []], _children: [] },
|
|
264
268
|
done: false
|
|
265
269
|
};
|
|
@@ -345,6 +349,7 @@ function runQueue(queue, type) {
|
|
|
345
349
|
}
|
|
346
350
|
function transitionComplete(transition) {
|
|
347
351
|
if (transition.done) return true;
|
|
352
|
+
if (transition.actions.length) return false;
|
|
348
353
|
let done = true;
|
|
349
354
|
for (let i = 0; i < transition.asyncNodes.length; i++) {
|
|
350
355
|
if (transition.asyncNodes[i]._statusFlags & STATUS_PENDING) {
|
|
@@ -355,11 +360,40 @@ function transitionComplete(transition) {
|
|
|
355
360
|
done && (transition.done = true);
|
|
356
361
|
return done;
|
|
357
362
|
}
|
|
358
|
-
function runInTransition(
|
|
363
|
+
function runInTransition(transition, fn) {
|
|
359
364
|
const prevTransition = activeTransition;
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
365
|
+
try {
|
|
366
|
+
activeTransition = transition;
|
|
367
|
+
return fn();
|
|
368
|
+
} finally {
|
|
369
|
+
activeTransition = prevTransition;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
function action(genFn) {
|
|
373
|
+
return (...args) => {
|
|
374
|
+
const iterator = genFn(...args);
|
|
375
|
+
globalQueue.initTransition();
|
|
376
|
+
let ctx = activeTransition;
|
|
377
|
+
ctx.actions.push(iterator);
|
|
378
|
+
const step = input => {
|
|
379
|
+
let nextValue = iterator.next(input);
|
|
380
|
+
if (nextValue instanceof Promise) return nextValue.then(process);
|
|
381
|
+
process(nextValue);
|
|
382
|
+
};
|
|
383
|
+
const process = result => {
|
|
384
|
+
if (result.done) {
|
|
385
|
+
ctx.actions.splice(ctx.actions.indexOf(iterator), 1);
|
|
386
|
+
activeTransition = ctx;
|
|
387
|
+
schedule();
|
|
388
|
+
flush();
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
const yielded = result.value;
|
|
392
|
+
if (yielded instanceof Promise) return yielded.then(step);
|
|
393
|
+
runInTransition(ctx, () => step(yielded));
|
|
394
|
+
};
|
|
395
|
+
runInTransition(ctx, () => step());
|
|
396
|
+
};
|
|
363
397
|
}
|
|
364
398
|
GlobalQueue._update = recompute;
|
|
365
399
|
GlobalQueue._dispose = disposeChildren;
|
|
@@ -426,7 +460,7 @@ function recompute(el, create = false) {
|
|
|
426
460
|
const valueChanged =
|
|
427
461
|
!el._equals ||
|
|
428
462
|
!el._equals(
|
|
429
|
-
el._pendingValue === NOT_PENDING || el._optimistic || honoraryOptimistic
|
|
463
|
+
el._pendingValue === NOT_PENDING || (el._optimistic && el._transition) || honoraryOptimistic
|
|
430
464
|
? el._value
|
|
431
465
|
: el._pendingValue,
|
|
432
466
|
value
|
|
@@ -449,7 +483,7 @@ function recompute(el, create = false) {
|
|
|
449
483
|
(!create || el._statusFlags & STATUS_PENDING) &&
|
|
450
484
|
!el._transition &&
|
|
451
485
|
globalQueue._pendingNodes.push(el);
|
|
452
|
-
el._transition && honoraryOptimistic && runInTransition(el, recompute);
|
|
486
|
+
el._transition && honoraryOptimistic && runInTransition(el._transition, () => recompute(el));
|
|
453
487
|
}
|
|
454
488
|
function handleAsync(el, result, setter) {
|
|
455
489
|
const isObject = typeof result === "object" && result !== null;
|
|
@@ -755,17 +789,6 @@ function read(el) {
|
|
|
755
789
|
}
|
|
756
790
|
}
|
|
757
791
|
}
|
|
758
|
-
if (pendingCheck) {
|
|
759
|
-
if (!el._pendingCheck) {
|
|
760
|
-
el._pendingCheck = signal(false);
|
|
761
|
-
el._pendingCheck._optimistic = true;
|
|
762
|
-
el._pendingCheck._set = v => setSignal(el._pendingCheck, v);
|
|
763
|
-
}
|
|
764
|
-
const prev = pendingCheck;
|
|
765
|
-
pendingCheck = null;
|
|
766
|
-
prev._value = read(el._pendingCheck) || prev._value;
|
|
767
|
-
pendingCheck = prev;
|
|
768
|
-
}
|
|
769
792
|
if (pendingValueCheck) {
|
|
770
793
|
if (!el._pendingSignal) {
|
|
771
794
|
el._pendingSignal = signal(el._value);
|
|
@@ -778,10 +801,23 @@ function read(el) {
|
|
|
778
801
|
pendingValueCheck = true;
|
|
779
802
|
}
|
|
780
803
|
}
|
|
781
|
-
|
|
782
|
-
|
|
804
|
+
const asyncCompute = el._firewall || el;
|
|
805
|
+
if (pendingCheck) {
|
|
806
|
+
if (!asyncCompute._pendingCheck) {
|
|
807
|
+
asyncCompute._pendingCheck = signal(false);
|
|
808
|
+
asyncCompute._pendingCheck._optimistic = true;
|
|
809
|
+
asyncCompute._pendingCheck._set = v => setSignal(asyncCompute._pendingCheck, v);
|
|
810
|
+
}
|
|
811
|
+
const prev = pendingCheck;
|
|
812
|
+
pendingCheck = null;
|
|
813
|
+
prev._value = read(asyncCompute._pendingCheck) || prev._value;
|
|
814
|
+
pendingCheck = prev;
|
|
815
|
+
}
|
|
816
|
+
if (!pendingCheck && asyncCompute._statusFlags & STATUS_PENDING) {
|
|
817
|
+
if ((c && !stale) || asyncCompute._statusFlags & STATUS_UNINITIALIZED || el._firewall)
|
|
818
|
+
throw asyncCompute._error;
|
|
783
819
|
else if (c && stale) {
|
|
784
|
-
setStatusFlags(c, c._statusFlags |
|
|
820
|
+
setStatusFlags(c, c._statusFlags | STATUS_PENDING, asyncCompute._error);
|
|
785
821
|
}
|
|
786
822
|
}
|
|
787
823
|
if (el._statusFlags & STATUS_ERROR) {
|
|
@@ -814,7 +850,9 @@ function setSignal(el, v) {
|
|
|
814
850
|
const valueChanged =
|
|
815
851
|
!el._equals ||
|
|
816
852
|
!el._equals(
|
|
817
|
-
el._pendingValue === NOT_PENDING || el._optimistic
|
|
853
|
+
el._pendingValue === NOT_PENDING || (el._optimistic && el._transition)
|
|
854
|
+
? el._value
|
|
855
|
+
: el._pendingValue,
|
|
818
856
|
v
|
|
819
857
|
);
|
|
820
858
|
if (!valueChanged && !el._statusFlags) return v;
|
|
@@ -928,6 +966,10 @@ function refresh(fn) {
|
|
|
928
966
|
let prevRefreshing = refreshing;
|
|
929
967
|
refreshing = true;
|
|
930
968
|
try {
|
|
969
|
+
if (typeof fn !== "function") {
|
|
970
|
+
recompute(fn[$REFRESH]);
|
|
971
|
+
return fn;
|
|
972
|
+
}
|
|
931
973
|
return untrack(fn);
|
|
932
974
|
} finally {
|
|
933
975
|
refreshing = prevRefreshing;
|
|
@@ -1136,11 +1178,7 @@ function unwrap(value) {
|
|
|
1136
1178
|
return value?.[$TARGET]?.[STORE_NODE] ?? value;
|
|
1137
1179
|
}
|
|
1138
1180
|
function getOverrideValue(value, override, nodes, key) {
|
|
1139
|
-
return
|
|
1140
|
-
? read(nodes[key])
|
|
1141
|
-
: override && key in override
|
|
1142
|
-
? override[key]
|
|
1143
|
-
: value[key];
|
|
1181
|
+
return override && key in override ? override[key] : value[key];
|
|
1144
1182
|
}
|
|
1145
1183
|
function getAllKeys(value, override, next) {
|
|
1146
1184
|
const keys = getKeys(value, override);
|
|
@@ -1226,10 +1264,12 @@ function applyState(next, state, keyFn, all) {
|
|
|
1226
1264
|
} else target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrap(next[j], target));
|
|
1227
1265
|
}
|
|
1228
1266
|
if (start < next.length) changed = true;
|
|
1229
|
-
} else if (
|
|
1267
|
+
} else if (next.length) {
|
|
1230
1268
|
for (let i = 0, len = next.length; i < len; i++) {
|
|
1231
1269
|
const item = getOverrideValue(previous, override, nodes, i);
|
|
1232
|
-
isWrappable(item)
|
|
1270
|
+
isWrappable(item)
|
|
1271
|
+
? applyState(next[i], wrap(item, target), keyFn, all)
|
|
1272
|
+
: target[STORE_NODE][i] && setSignal(target[STORE_NODE][i], next[i]);
|
|
1233
1273
|
}
|
|
1234
1274
|
}
|
|
1235
1275
|
if (prevLength !== next.length) {
|
|
@@ -1279,36 +1319,74 @@ function reconcile(value, key, all = false) {
|
|
|
1279
1319
|
function createProjectionInternal(fn, initialValue = {}, options) {
|
|
1280
1320
|
let node;
|
|
1281
1321
|
const wrappedMap = new WeakMap();
|
|
1322
|
+
const wrapper = s => {
|
|
1323
|
+
s[STORE_WRAP] = wrapProjection;
|
|
1324
|
+
s[STORE_LOOKUP] = wrappedMap;
|
|
1325
|
+
Object.defineProperty(s, STORE_FIREWALL, {
|
|
1326
|
+
get() {
|
|
1327
|
+
return node;
|
|
1328
|
+
},
|
|
1329
|
+
configurable: true
|
|
1330
|
+
});
|
|
1331
|
+
};
|
|
1282
1332
|
const wrapProjection = source => {
|
|
1283
1333
|
if (wrappedMap.has(source)) return wrappedMap.get(source);
|
|
1284
1334
|
if (source[$TARGET]?.[STORE_WRAP] === wrapProjection) return source;
|
|
1285
|
-
const wrapped = createStoreProxy(source, storeTraps,
|
|
1286
|
-
[STORE_WRAP]: wrapProjection,
|
|
1287
|
-
[STORE_LOOKUP]: wrappedMap,
|
|
1288
|
-
[STORE_FIREWALL]() {
|
|
1289
|
-
return node;
|
|
1290
|
-
}
|
|
1291
|
-
});
|
|
1335
|
+
const wrapped = createStoreProxy(source, storeTraps, wrapper);
|
|
1292
1336
|
wrappedMap.set(source, wrapped);
|
|
1293
1337
|
return wrapped;
|
|
1294
1338
|
};
|
|
1295
1339
|
const wrappedStore = wrapProjection(initialValue);
|
|
1296
1340
|
node = computed(() => {
|
|
1297
1341
|
const owner = node || getOwner();
|
|
1298
|
-
storeSetter(wrappedStore, s => {
|
|
1342
|
+
storeSetter(new Proxy(wrappedStore, writeTraps), s => {
|
|
1299
1343
|
const value = handleAsync(owner, fn(s), value => {
|
|
1300
|
-
value !==
|
|
1344
|
+
value !== wrappedStore &&
|
|
1301
1345
|
value !== undefined &&
|
|
1302
1346
|
storeSetter(wrappedStore, reconcile(value, options?.key || "id", options?.all));
|
|
1347
|
+
setSignal(node, undefined);
|
|
1303
1348
|
});
|
|
1304
|
-
value !==
|
|
1349
|
+
value !== wrappedStore &&
|
|
1350
|
+
value !== undefined &&
|
|
1351
|
+
reconcile(value, options?.key || "id", options?.all)(wrappedStore);
|
|
1305
1352
|
});
|
|
1306
1353
|
});
|
|
1354
|
+
node._preventAutoDisposal = true;
|
|
1307
1355
|
return { store: wrappedStore, node: node };
|
|
1308
1356
|
}
|
|
1309
1357
|
function createProjection(fn, initialValue = {}, options) {
|
|
1310
1358
|
return createProjectionInternal(fn, initialValue, options).store;
|
|
1311
1359
|
}
|
|
1360
|
+
const writeTraps = {
|
|
1361
|
+
get(_, prop) {
|
|
1362
|
+
let value;
|
|
1363
|
+
setWriteOverride(true);
|
|
1364
|
+
try {
|
|
1365
|
+
value = _[prop];
|
|
1366
|
+
} finally {
|
|
1367
|
+
setWriteOverride(false);
|
|
1368
|
+
}
|
|
1369
|
+
return typeof value === "object" && value !== null ? new Proxy(value, writeTraps) : value;
|
|
1370
|
+
},
|
|
1371
|
+
set(_, prop, value) {
|
|
1372
|
+
setWriteOverride(true);
|
|
1373
|
+
try {
|
|
1374
|
+
_[prop] = value;
|
|
1375
|
+
} finally {
|
|
1376
|
+
setWriteOverride(false);
|
|
1377
|
+
}
|
|
1378
|
+
return true;
|
|
1379
|
+
},
|
|
1380
|
+
deleteProperty(_, prop) {
|
|
1381
|
+
setWriteOverride(true);
|
|
1382
|
+
try {
|
|
1383
|
+
delete _[prop];
|
|
1384
|
+
} finally {
|
|
1385
|
+
setWriteOverride(false);
|
|
1386
|
+
}
|
|
1387
|
+
return true;
|
|
1388
|
+
}
|
|
1389
|
+
};
|
|
1312
1390
|
const $TRACK = Symbol("STORE_TRACK"),
|
|
1313
1391
|
$DEEP = Symbol("STORE_DEEP"),
|
|
1314
1392
|
$TARGET = Symbol("STORE_TARGET"),
|
|
@@ -1328,7 +1406,7 @@ function createStoreProxy(value, traps = storeTraps, extend) {
|
|
|
1328
1406
|
newTarget = [];
|
|
1329
1407
|
newTarget.v = value;
|
|
1330
1408
|
} else newTarget = { v: value };
|
|
1331
|
-
extend &&
|
|
1409
|
+
extend && extend(newTarget);
|
|
1332
1410
|
return (newTarget[$PROXY] = new Proxy(newTarget, traps));
|
|
1333
1411
|
}
|
|
1334
1412
|
const storeLookup = new WeakMap();
|
|
@@ -1341,6 +1419,13 @@ function wrap(value, target) {
|
|
|
1341
1419
|
function isWrappable(obj) {
|
|
1342
1420
|
return obj != null && typeof obj === "object" && !Object.isFrozen(obj);
|
|
1343
1421
|
}
|
|
1422
|
+
let writeOverride = false;
|
|
1423
|
+
function setWriteOverride(value) {
|
|
1424
|
+
writeOverride = value;
|
|
1425
|
+
}
|
|
1426
|
+
function writeOnly(proxy) {
|
|
1427
|
+
return writeOverride || !!Writing?.has(proxy);
|
|
1428
|
+
}
|
|
1344
1429
|
function getNodes(target, type) {
|
|
1345
1430
|
let nodes = target[type];
|
|
1346
1431
|
if (!nodes) target[type] = nodes = Object.create(null);
|
|
@@ -1361,9 +1446,7 @@ function getNode(nodes, property, value, firewall, equals = isEqual) {
|
|
|
1361
1446
|
}
|
|
1362
1447
|
function trackSelf(target, symbol = $TRACK) {
|
|
1363
1448
|
getObserver() &&
|
|
1364
|
-
read(
|
|
1365
|
-
getNode(getNodes(target, STORE_NODE), symbol, undefined, target[STORE_FIREWALL]?.(), false)
|
|
1366
|
-
);
|
|
1449
|
+
read(getNode(getNodes(target, STORE_NODE), symbol, undefined, target[STORE_FIREWALL], false));
|
|
1367
1450
|
}
|
|
1368
1451
|
function getKeys(source, override, enumerable = true) {
|
|
1369
1452
|
const baseKeys = untrack(() => (enumerable ? Object.keys(source) : Reflect.ownKeys(source)));
|
|
@@ -1389,6 +1472,7 @@ const storeTraps = {
|
|
|
1389
1472
|
get(target, property, receiver) {
|
|
1390
1473
|
if (property === $TARGET) return target;
|
|
1391
1474
|
if (property === $PROXY) return receiver;
|
|
1475
|
+
if (property === $REFRESH) return target[STORE_FIREWALL];
|
|
1392
1476
|
if (property === $TRACK || property === $DEEP) {
|
|
1393
1477
|
trackSelf(target, property);
|
|
1394
1478
|
return receiver;
|
|
@@ -1402,7 +1486,7 @@ const storeTraps = {
|
|
|
1402
1486
|
const desc = Object.getOwnPropertyDescriptor(storeValue, property);
|
|
1403
1487
|
if (desc && desc.get) return desc.get.call(receiver);
|
|
1404
1488
|
}
|
|
1405
|
-
if (
|
|
1489
|
+
if (writeOnly(receiver)) {
|
|
1406
1490
|
let value =
|
|
1407
1491
|
tracked && (overridden || !proxySource)
|
|
1408
1492
|
? tracked._pendingValue !== NOT_PENDING
|
|
@@ -1412,7 +1496,7 @@ const storeTraps = {
|
|
|
1412
1496
|
value === $DELETED && (value = undefined);
|
|
1413
1497
|
if (!isWrappable(value)) return value;
|
|
1414
1498
|
const wrapped = wrap(value, target);
|
|
1415
|
-
Writing
|
|
1499
|
+
Writing?.add(wrapped);
|
|
1416
1500
|
return wrapped;
|
|
1417
1501
|
}
|
|
1418
1502
|
let value = tracked
|
|
@@ -1435,7 +1519,7 @@ const storeTraps = {
|
|
|
1435
1519
|
nodes,
|
|
1436
1520
|
property,
|
|
1437
1521
|
isWrappable(value) ? wrap(value, target) : value,
|
|
1438
|
-
target[STORE_FIREWALL]
|
|
1522
|
+
target[STORE_FIREWALL]
|
|
1439
1523
|
)
|
|
1440
1524
|
);
|
|
1441
1525
|
}
|
|
@@ -1449,12 +1533,12 @@ const storeTraps = {
|
|
|
1449
1533
|
? target[STORE_OVERRIDE][property] !== $DELETED
|
|
1450
1534
|
: property in target[STORE_VALUE];
|
|
1451
1535
|
getObserver() &&
|
|
1452
|
-
read(getNode(getNodes(target, STORE_HAS), property, has, target[STORE_FIREWALL]
|
|
1536
|
+
read(getNode(getNodes(target, STORE_HAS), property, has, target[STORE_FIREWALL]));
|
|
1453
1537
|
return has;
|
|
1454
1538
|
},
|
|
1455
1539
|
set(target, property, rawValue) {
|
|
1456
1540
|
const store = target[$PROXY];
|
|
1457
|
-
if (
|
|
1541
|
+
if (writeOnly(store)) {
|
|
1458
1542
|
untrack(() => {
|
|
1459
1543
|
const state = target[STORE_VALUE];
|
|
1460
1544
|
const base = state[property];
|
|
@@ -1489,7 +1573,7 @@ const storeTraps = {
|
|
|
1489
1573
|
return true;
|
|
1490
1574
|
},
|
|
1491
1575
|
deleteProperty(target, property) {
|
|
1492
|
-
if (
|
|
1576
|
+
if (writeOnly(target[$PROXY]) && target[STORE_OVERRIDE]?.[property] !== $DELETED) {
|
|
1493
1577
|
untrack(() => {
|
|
1494
1578
|
const prev =
|
|
1495
1579
|
target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
|
|
@@ -2214,6 +2298,7 @@ export {
|
|
|
2214
2298
|
NoOwnerError,
|
|
2215
2299
|
NotReadyError,
|
|
2216
2300
|
SUPPORTS_PROXY,
|
|
2301
|
+
action,
|
|
2217
2302
|
createBoundary,
|
|
2218
2303
|
createContext,
|
|
2219
2304
|
createEffect,
|