querysub 0.431.0 → 0.432.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.
- package/.cursor/rules/css.mdc +58 -0
- package/.cursor/rules/general.mdc +35 -0
- package/.cursor/rules/react.mdc +27 -0
- package/package.json +2 -2
- package/src/-f-node-discovery/NodeDiscovery.ts +1 -2
- package/src/-h-path-value-serialize/PathValueSerializer.ts +1056 -1056
- package/src/0-path-value-core/pathValueCore.ts +1 -1
- package/src/2-proxy/PathValueProxyWatcher.ts +4 -0
- package/src/2-proxy/schema2.ts +1 -1
- package/src/4-querysub/Querysub.ts +3 -2
- package/src/misc/PromiseRace.ts +0 -101
|
@@ -14,7 +14,7 @@ import { pathValueSerializer } from "../-h-path-value-serialize/PathValueSeriali
|
|
|
14
14
|
import { AuthoritySpec, PathRouter } from "./PathRouter";
|
|
15
15
|
import { formatTime } from "socket-function/src/formatting/format";
|
|
16
16
|
import { isOwnNodeId } from "../-f-node-discovery/NodeDiscovery";
|
|
17
|
-
import { PromiseRace } from "
|
|
17
|
+
import { PromiseRace } from "socket-function/src/PromiseRace";
|
|
18
18
|
|
|
19
19
|
import yargs from "yargs";
|
|
20
20
|
import { PromiseObj } from "../promise";
|
|
@@ -554,6 +554,7 @@ export class PathValueProxyWatcher {
|
|
|
554
554
|
public getCallbackPathValue = (pathStr: string, syncParentKeys?: "parentKeys"): PathValue | undefined => {
|
|
555
555
|
const watcher = this.runningWatcher;
|
|
556
556
|
if (!watcher) {
|
|
557
|
+
debugger;
|
|
557
558
|
throw new Error(`Tried to get path "${pathStr}" outside of a watcher function.`);
|
|
558
559
|
}
|
|
559
560
|
|
|
@@ -652,6 +653,7 @@ export class PathValueProxyWatcher {
|
|
|
652
653
|
}
|
|
653
654
|
const watcher = this.runningWatcher;
|
|
654
655
|
if (!watcher) {
|
|
656
|
+
debugger;
|
|
655
657
|
throw new Error(`Tried to get path "${pathStr}" outside of a watcher function.`);
|
|
656
658
|
}
|
|
657
659
|
|
|
@@ -762,6 +764,7 @@ export class PathValueProxyWatcher {
|
|
|
762
764
|
if (lastPart.startsWith("__") || lastPart === "type") {
|
|
763
765
|
return;
|
|
764
766
|
}
|
|
767
|
+
debugger;
|
|
765
768
|
throw new Error(`Tried to set path "${pathStr}" outside of a watcher function.`);
|
|
766
769
|
}
|
|
767
770
|
if (!watcher.options.canWrite) {
|
|
@@ -899,6 +902,7 @@ export class PathValueProxyWatcher {
|
|
|
899
902
|
|
|
900
903
|
const watcher = this.runningWatcher;
|
|
901
904
|
if (!watcher) {
|
|
905
|
+
debugger;
|
|
902
906
|
throw new Error(`Tried to getKeys on path "${pathStr}" outside of a watcher function.`);
|
|
903
907
|
}
|
|
904
908
|
|
package/src/2-proxy/schema2.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
import "../inject";
|
|
5
5
|
|
|
6
6
|
// Shim Promise.race, as no one wants their promises to leak...
|
|
7
|
-
import {
|
|
8
|
-
Promise.race =
|
|
7
|
+
import { PromiseRace } from "socket-function/src/promiseRace";
|
|
8
|
+
Promise.race = PromiseRace;
|
|
9
9
|
|
|
10
10
|
import { shimDateNow } from "socket-function/time/trueTimeShim";
|
|
11
11
|
shimDateNow();
|
|
@@ -378,6 +378,7 @@ export class Querysub {
|
|
|
378
378
|
public static fastReadAsync<T>(fnc: () => T, options?: Partial<WatcherOptions<T>>) {
|
|
379
379
|
return Querysub.serviceWrite(fnc, { ...options, allowProxyResults: true, noWaitForCommit: true });
|
|
380
380
|
}
|
|
381
|
+
public static readLocal = Querysub.localRead;
|
|
381
382
|
public static localRead<T>(fnc: () => T, options?: Partial<WatcherOptions<T>>) {
|
|
382
383
|
return proxyWatcher.runOnce({
|
|
383
384
|
watchFunction: fnc,
|
package/src/misc/PromiseRace.ts
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
/** Fixed Promise.race, which doesn't leak promises values. Promises still leak, but a Promise is < 100 bytes,
|
|
2
|
-
* where as the promise value might be huge.
|
|
3
|
-
*/
|
|
4
|
-
export function PromiseRace<T extends any[]>(promises: { [K in keyof T]: Promise<T[K]> }): Promise<T[number]> {
|
|
5
|
-
return new PromiseLessLeaky((resolve: any, reject: any) => {
|
|
6
|
-
function onFinally() {
|
|
7
|
-
for (let promise of promises) {
|
|
8
|
-
if (promise && typeof promise === "object" && promise instanceof Promise) {
|
|
9
|
-
let callbackObj = promiseCallbacks.get(promise);
|
|
10
|
-
if (!callbackObj) continue;
|
|
11
|
-
remove(callbackObj.onResolve, resolve);
|
|
12
|
-
remove(callbackObj.onReject, reject);
|
|
13
|
-
remove(callbackObj.onFinally, onFinally);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
for (let promise of promises) {
|
|
18
|
-
// NOTE: This "if" statement greatly reduce leaks, although it might
|
|
19
|
-
// reduce speed as well?
|
|
20
|
-
if (promise && typeof promise === "object" && promise instanceof Promise) {
|
|
21
|
-
let callbackObj = promiseCallbacks.get(promise);
|
|
22
|
-
if (!callbackObj) {
|
|
23
|
-
callbackObj = {
|
|
24
|
-
onResolve: [],
|
|
25
|
-
onReject: [],
|
|
26
|
-
onFinally: [],
|
|
27
|
-
};
|
|
28
|
-
promiseCallbacks.set(promise, callbackObj);
|
|
29
|
-
connectPromiseToCallbackObj(promise, callbackObj);
|
|
30
|
-
}
|
|
31
|
-
callbackObj.onResolve.push(resolve);
|
|
32
|
-
callbackObj.onReject.push(reject);
|
|
33
|
-
callbackObj.onFinally.push(onFinally);
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
Promise.resolve(promise).then(resolve, reject);
|
|
38
|
-
}
|
|
39
|
-
}) as any;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Less leaky promise.
|
|
43
|
-
// See https://github.com/nodejs/node/issues/17469
|
|
44
|
-
// See https://bugs.chromium.org/p/v8/issues/detail?id=9858#c9
|
|
45
|
-
// Basically, make resolve/reject weakly reference the Promise, so that
|
|
46
|
-
// resolved promises aren't kept alive. The `resolve` function is still leaked
|
|
47
|
-
// itself, but at least it doesn't leak the underlying data.
|
|
48
|
-
// IMPORTANT! This still leaks! So... maybe don't even use Promise.race?
|
|
49
|
-
class PromiseLessLeaky extends Promise<any> {
|
|
50
|
-
constructor(executor: any) {
|
|
51
|
-
super((resolve, reject) => {
|
|
52
|
-
executor(
|
|
53
|
-
function PromiseLessLeakyResolved(value: any) {
|
|
54
|
-
let callback = resolve;
|
|
55
|
-
resolve = undefined as any;
|
|
56
|
-
reject = undefined as any;
|
|
57
|
-
if (callback) {
|
|
58
|
-
callback(value);
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
function PromiseLessLeakyRejected(value: any) {
|
|
62
|
-
let callback = reject;
|
|
63
|
-
resolve = undefined as any;
|
|
64
|
-
reject = undefined as any;
|
|
65
|
-
if (callback) {
|
|
66
|
-
callback(value);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
);
|
|
70
|
-
executor = undefined;
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
function remove(list: any, value: any) {
|
|
75
|
-
let index = list.indexOf(value);
|
|
76
|
-
if (index >= 0) {
|
|
77
|
-
list.splice(index, 1);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
const promiseCallbacks = new WeakMap();
|
|
81
|
-
|
|
82
|
-
function connectPromiseToCallbackObj(promise: any, callbackObj: any) {
|
|
83
|
-
// NOTE: If the promise stays alive forever... this will leak callbackObj. BUT,
|
|
84
|
-
// it is only called once per promise, ever, so... the leak isn't so bad!
|
|
85
|
-
promise.then(
|
|
86
|
-
(value: any) => {
|
|
87
|
-
for (let fnc of callbackObj.onResolve) {
|
|
88
|
-
try { fnc(value); } finally { }
|
|
89
|
-
}
|
|
90
|
-
},
|
|
91
|
-
(value: any) => {
|
|
92
|
-
for (let fnc of callbackObj.onReject) {
|
|
93
|
-
try { fnc(value); } finally { }
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
).finally(() => {
|
|
97
|
-
for (let fnc of callbackObj.onFinally) {
|
|
98
|
-
try { fnc(); } finally { }
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
}
|