socket-function 0.9.2 → 0.9.4

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 (45) hide show
  1. package/.eslintrc.js +50 -50
  2. package/SocketFunction.ts +280 -280
  3. package/SocketFunctionTypes.ts +90 -90
  4. package/hot/HotReloadController.ts +105 -105
  5. package/mobx/UrlParam.ts +39 -39
  6. package/mobx/observer.tsx +49 -49
  7. package/mobx/promiseToObservable.tsx +41 -41
  8. package/package.json +2 -2
  9. package/require/CSSShim.ts +19 -19
  10. package/require/RequireController.ts +252 -252
  11. package/require/buffer.js +2368 -2368
  12. package/require/compileFlags.ts +44 -44
  13. package/require/require.html +13 -13
  14. package/require/require.js +462 -462
  15. package/spec.txt +115 -115
  16. package/src/CallFactory.ts +389 -389
  17. package/src/JSONLACKS/JSONLACKS.generated.js +17 -17
  18. package/src/JSONLACKS/JSONLACKS.pegjs +247 -247
  19. package/src/JSONLACKS/JSONLACKS.ts +429 -429
  20. package/src/args.ts +21 -21
  21. package/src/batching.ts +170 -170
  22. package/src/caching.ts +324 -318
  23. package/src/callHTTPHandler.ts +203 -203
  24. package/src/callManager.ts +134 -134
  25. package/src/certStore.ts +29 -29
  26. package/src/fixLargeNetworkCalls.ts +8 -8
  27. package/src/formatting/colors.ts +78 -78
  28. package/src/formatting/format.ts +160 -160
  29. package/src/formatting/logColors.ts +17 -17
  30. package/src/misc.ts +303 -302
  31. package/src/nodeCache.ts +92 -92
  32. package/src/nodeProxy.ts +54 -54
  33. package/src/profiling/getOwnTime.ts +142 -142
  34. package/src/profiling/measure.ts +273 -273
  35. package/src/profiling/stats.ts +212 -212
  36. package/src/profiling/tcpLagProxy.ts +63 -63
  37. package/src/storagePath.ts +10 -10
  38. package/src/tlsParsing.ts +96 -96
  39. package/src/types.ts +8 -8
  40. package/src/webSocketServer.ts +250 -250
  41. package/test/client.css +2 -2
  42. package/test/client.ts +46 -46
  43. package/test/server.ts +43 -43
  44. package/test/shared.ts +52 -52
  45. package/tsconfig.json +26 -26
package/src/args.ts CHANGED
@@ -1,22 +1,22 @@
1
- import { lazy } from "./caching";
2
-
3
- export const getArgs = lazy(() => {
4
- let args = process.argv.slice(2);
5
- let argObj: { [key: string]: string | undefined } = {};
6
- for (let arg of args) {
7
- if (arg.startsWith("-")) {
8
- arg = arg.slice(1);
9
- }
10
- if (arg.startsWith("-")) {
11
- arg = arg.slice(1);
12
- }
13
- if (arg.includes("=")) {
14
- let key = arg.split("=")[0];
15
- let value = arg.split("=").slice(1).join("=");
16
- argObj[key] = value;
17
- } else {
18
- argObj[arg] = "true";
19
- }
20
- }
21
- return argObj;
1
+ import { lazy } from "./caching";
2
+
3
+ export const getArgs = lazy(() => {
4
+ let args = process.argv.slice(2);
5
+ let argObj: { [key: string]: string | undefined } = {};
6
+ for (let arg of args) {
7
+ if (arg.startsWith("-")) {
8
+ arg = arg.slice(1);
9
+ }
10
+ if (arg.startsWith("-")) {
11
+ arg = arg.slice(1);
12
+ }
13
+ if (arg.includes("=")) {
14
+ let key = arg.split("=")[0];
15
+ let value = arg.split("=").slice(1).join("=");
16
+ argObj[key] = value;
17
+ } else {
18
+ argObj[arg] = "true";
19
+ }
20
+ }
21
+ return argObj;
22
22
  });
package/src/batching.ts CHANGED
@@ -1,171 +1,171 @@
1
- import { isNode } from "./misc";
2
- import { measureWrap } from "./profiling/measure";
3
-
4
- /*
5
- "numbers" use setTimeout
6
- "afterpromises" uses a microtask, see https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide
7
- "afterio" uses setImmediate, which will be after all pending and all created promises
8
- (in the browser it is likely setImmediate will be shimmed with setTimeout)
9
- "immediate" uses setImmediate, but if not available uses "afterpromises"
10
- - The ensures a prompt return, without resorting to setTimeout in the browser (which will cause
11
- the callback to be delayed a frame).
12
- */
13
- export type DelayType = number | "afterio" | "immediate" | "afterpromises";
14
- export function delay(delayTime: DelayType): Promise<void> {
15
- if (delayTime === "afterio") {
16
- return new Promise<void>(resolve => setImmediate(resolve));
17
- } else if (delayTime === "afterpromises") {
18
- // NOTE: We use a promise here as it might be a bit easier to debug than queueMicrotask.
19
- // It is equivalent though...
20
- return Promise.resolve();
21
- } else if (delayTime === "immediate") {
22
- if (isNode()) {
23
- return new Promise<void>(resolve => setImmediate(resolve));
24
- } else {
25
- return delay("afterpromises");
26
- }
27
- } else {
28
- // NOTE: setTimeout can't wait this short of a time, so just setImmediate. This should be hard to distinguish
29
- // anyways, as setImmediate (at least in nodejs), should happen after io, so... it should just work
30
- // (the only difference is there will be less unnecessary delay).
31
- if (delayTime < 10) {
32
- return delay("immediate");
33
- }
34
- return new Promise<void>(resolve => setTimeout(resolve, delayTime));
35
- }
36
- }
37
-
38
- export function batchFunction<Arg, Result = void>(
39
- config: {
40
- delay: DelayType;
41
- /** Instead of immediately waiting delay, starts by waiting 0ms, and every call increments the delay factor
42
- * by 1. Delay is `factor * (delay / throttleWindow)`. For every delay interval we have no calls, we decrease by
43
- * no_calls/delay.
44
- * - This essentially turns delay into a `calls per second` type indicator (ex, 10ms is 100 callers
45
- * per second, 500ms is 2 calls, etc), which is accurate over delay * throttleWindow time.
46
- */
47
- throttleWindow?: number;
48
- name?: string;
49
- },
50
- fnc: (arg: Arg[]) => (Promise<Result> | Result)
51
- ): (arg: Arg) => Promise<Result> {
52
- fnc = measureWrap(fnc, config.name);
53
-
54
- let prevPromise: Promise<Result> | undefined;
55
- let batched: {
56
- args: Arg[];
57
- promise: Promise<Result>;
58
- } | undefined;
59
- let curDelay = config.delay;
60
- let delayRamp = 0;
61
- if (config.throttleWindow && typeof curDelay === "number") {
62
- delayRamp = curDelay / config.throttleWindow;
63
- }
64
- let delayTime = 0;
65
- if (typeof curDelay === "number") {
66
- delayTime = curDelay;
67
- }
68
- let countSinceBreak = 0;
69
- let lastCall = 0;
70
- return async arg => {
71
- let now = Date.now();
72
- if (delayRamp) {
73
- let savedCount = (now - lastCall) / delayTime;
74
- if (savedCount >= 1) {
75
- countSinceBreak -= savedCount;
76
- }
77
- if (countSinceBreak < 0) {
78
- countSinceBreak = 0;
79
- }
80
-
81
- countSinceBreak++;
82
- // Set the max fairly high, as we basically ignore small delay times, so we need a high max to allow
83
- // our delay to even apply!
84
- curDelay = Math.min(delayTime * 20, delayRamp * countSinceBreak);
85
- }
86
- lastCall = now;
87
-
88
- if (!batched) {
89
- await prevPromise;
90
- }
91
- if (batched) {
92
- batched.args.push(arg);
93
- return await batched.promise;
94
- }
95
-
96
- let args: Arg[] = [arg];
97
- let promise = Promise.resolve().then(async () => {
98
- await delay(curDelay);
99
- // After we call the function, we can no longer accept args
100
- batched = undefined;
101
- return await fnc(args);
102
- });
103
- batched = {
104
- args,
105
- promise,
106
- };
107
- // We need to prevent new calls from starting when the previous call can no longer accept
108
- // args, BUT, before it has finished.
109
- prevPromise = batched.promise;
110
-
111
- return await promise;
112
- };
113
- }
114
-
115
- export function runInSerial<T extends (...args: any[]) => Promise<any>>(fnc: T): T {
116
- let updateQueue: (() => void)[] = [];
117
-
118
- return (async (...args: any[]) => {
119
- const queueWasEmpty = updateQueue.length === 0;
120
- if (!queueWasEmpty) {
121
- // Wait for the previous promise to resolve
122
- await new Promise<void>(resolve => updateQueue.push(resolve));
123
- }
124
- updateQueue.push(() => { });
125
-
126
- try {
127
- return await fnc(...args);
128
- } finally {
129
- // Pop ourself off
130
- updateQueue.shift();
131
- // Resolve the next promise
132
- updateQueue[0]?.();
133
- }
134
- }) as T;
135
- }
136
-
137
- export function runInfinitePoll(
138
- delayTime: number,
139
- fnc: () => Promise<void> | void
140
- ) {
141
- void (async () => {
142
- while (true) {
143
- await delay(delayTime);
144
- try {
145
- await fnc();
146
- } catch (e: any) {
147
- console.error(`Error in infinite poll ${fnc.name || fnc.toString().slice(0, 100).split("\n").slice(0, 2).join("\n")} (continuing poll loop)\n${e.stack}`);
148
- }
149
- }
150
- })();
151
- }
152
-
153
- export async function runInfinitePollCallAtStart(
154
- delayTime: number,
155
- fnc: () => Promise<void> | void
156
- ) {
157
- try {
158
- return await fnc();
159
- } finally {
160
- void (async () => {
161
- while (true) {
162
- await delay(delayTime);
163
- try {
164
- await fnc();
165
- } catch (e: any) {
166
- console.error(`Error in infinite poll ${fnc.name} (continuing poll loop)\n${e.stack}`);
167
- }
168
- }
169
- })();
170
- }
1
+ import { isNode } from "./misc";
2
+ import { measureWrap } from "./profiling/measure";
3
+
4
+ /*
5
+ "numbers" use setTimeout
6
+ "afterpromises" uses a microtask, see https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide
7
+ "afterio" uses setImmediate, which will be after all pending and all created promises
8
+ (in the browser it is likely setImmediate will be shimmed with setTimeout)
9
+ "immediate" uses setImmediate, but if not available uses "afterpromises"
10
+ - The ensures a prompt return, without resorting to setTimeout in the browser (which will cause
11
+ the callback to be delayed a frame).
12
+ */
13
+ export type DelayType = number | "afterio" | "immediate" | "afterpromises";
14
+ export function delay(delayTime: DelayType): Promise<void> {
15
+ if (delayTime === "afterio") {
16
+ return new Promise<void>(resolve => setImmediate(resolve));
17
+ } else if (delayTime === "afterpromises") {
18
+ // NOTE: We use a promise here as it might be a bit easier to debug than queueMicrotask.
19
+ // It is equivalent though...
20
+ return Promise.resolve();
21
+ } else if (delayTime === "immediate") {
22
+ if (isNode()) {
23
+ return new Promise<void>(resolve => setImmediate(resolve));
24
+ } else {
25
+ return delay("afterpromises");
26
+ }
27
+ } else {
28
+ // NOTE: setTimeout can't wait this short of a time, so just setImmediate. This should be hard to distinguish
29
+ // anyways, as setImmediate (at least in nodejs), should happen after io, so... it should just work
30
+ // (the only difference is there will be less unnecessary delay).
31
+ if (delayTime < 10) {
32
+ return delay("immediate");
33
+ }
34
+ return new Promise<void>(resolve => setTimeout(resolve, delayTime));
35
+ }
36
+ }
37
+
38
+ export function batchFunction<Arg, Result = void>(
39
+ config: {
40
+ delay: DelayType;
41
+ /** Instead of immediately waiting delay, starts by waiting 0ms, and every call increments the delay factor
42
+ * by 1. Delay is `factor * (delay / throttleWindow)`. For every delay interval we have no calls, we decrease by
43
+ * no_calls/delay.
44
+ * - This essentially turns delay into a `calls per second` type indicator (ex, 10ms is 100 callers
45
+ * per second, 500ms is 2 calls, etc), which is accurate over delay * throttleWindow time.
46
+ */
47
+ throttleWindow?: number;
48
+ name?: string;
49
+ },
50
+ fnc: (arg: Arg[]) => (Promise<Result> | Result)
51
+ ): (arg: Arg) => Promise<Result> {
52
+ fnc = measureWrap(fnc, config.name);
53
+
54
+ let prevPromise: Promise<Result> | undefined;
55
+ let batched: {
56
+ args: Arg[];
57
+ promise: Promise<Result>;
58
+ } | undefined;
59
+ let curDelay = config.delay;
60
+ let delayRamp = 0;
61
+ if (config.throttleWindow && typeof curDelay === "number") {
62
+ delayRamp = curDelay / config.throttleWindow;
63
+ }
64
+ let delayTime = 0;
65
+ if (typeof curDelay === "number") {
66
+ delayTime = curDelay;
67
+ }
68
+ let countSinceBreak = 0;
69
+ let lastCall = 0;
70
+ return async arg => {
71
+ let now = Date.now();
72
+ if (delayRamp) {
73
+ let savedCount = (now - lastCall) / delayTime;
74
+ if (savedCount >= 1) {
75
+ countSinceBreak -= savedCount;
76
+ }
77
+ if (countSinceBreak < 0) {
78
+ countSinceBreak = 0;
79
+ }
80
+
81
+ countSinceBreak++;
82
+ // Set the max fairly high, as we basically ignore small delay times, so we need a high max to allow
83
+ // our delay to even apply!
84
+ curDelay = Math.min(delayTime * 20, delayRamp * countSinceBreak);
85
+ }
86
+ lastCall = now;
87
+
88
+ if (!batched) {
89
+ await prevPromise;
90
+ }
91
+ if (batched) {
92
+ batched.args.push(arg);
93
+ return await batched.promise;
94
+ }
95
+
96
+ let args: Arg[] = [arg];
97
+ let promise = Promise.resolve().then(async () => {
98
+ await delay(curDelay);
99
+ // After we call the function, we can no longer accept args
100
+ batched = undefined;
101
+ return await fnc(args);
102
+ });
103
+ batched = {
104
+ args,
105
+ promise,
106
+ };
107
+ // We need to prevent new calls from starting when the previous call can no longer accept
108
+ // args, BUT, before it has finished.
109
+ prevPromise = batched.promise;
110
+
111
+ return await promise;
112
+ };
113
+ }
114
+
115
+ export function runInSerial<T extends (...args: any[]) => Promise<any>>(fnc: T): T {
116
+ let updateQueue: (() => void)[] = [];
117
+
118
+ return (async (...args: any[]) => {
119
+ const queueWasEmpty = updateQueue.length === 0;
120
+ if (!queueWasEmpty) {
121
+ // Wait for the previous promise to resolve
122
+ await new Promise<void>(resolve => updateQueue.push(resolve));
123
+ }
124
+ updateQueue.push(() => { });
125
+
126
+ try {
127
+ return await fnc(...args);
128
+ } finally {
129
+ // Pop ourself off
130
+ updateQueue.shift();
131
+ // Resolve the next promise
132
+ updateQueue[0]?.();
133
+ }
134
+ }) as T;
135
+ }
136
+
137
+ export function runInfinitePoll(
138
+ delayTime: number,
139
+ fnc: () => Promise<void> | void
140
+ ) {
141
+ void (async () => {
142
+ while (true) {
143
+ await delay(delayTime);
144
+ try {
145
+ await fnc();
146
+ } catch (e: any) {
147
+ console.error(`Error in infinite poll ${fnc.name || fnc.toString().slice(0, 100).split("\n").slice(0, 2).join("\n")} (continuing poll loop)\n${e.stack}`);
148
+ }
149
+ }
150
+ })();
151
+ }
152
+
153
+ export async function runInfinitePollCallAtStart(
154
+ delayTime: number,
155
+ fnc: () => Promise<void> | void
156
+ ) {
157
+ try {
158
+ return await fnc();
159
+ } finally {
160
+ void (async () => {
161
+ while (true) {
162
+ await delay(delayTime);
163
+ try {
164
+ await fnc();
165
+ } catch (e: any) {
166
+ console.error(`Error in infinite poll ${fnc.name} (continuing poll loop)\n${e.stack}`);
167
+ }
168
+ }
169
+ })();
170
+ }
171
171
  }