socket-function 0.128.0 → 0.130.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/SocketFunction.ts CHANGED
@@ -63,6 +63,7 @@ export class SocketFunction {
63
63
  // If you have HTTP resources that require cookies you might to set `SocketFunction.COEP = "require-corp"`
64
64
  // - Cross-origin-resource-policy.
65
65
  public static COEP = "credentialless";
66
+ // NOTE: This COOP and COEP defaults are required so window.crossOriginIsolated will be true.
66
67
  public static COOP = "same-origin";
67
68
 
68
69
  // In retrospect... dynamically changing the wire serializer is a BAD idea. If any calls happen
@@ -84,6 +84,8 @@ export type ClientHookContext = {
84
84
  overrideResult?: unknown;
85
85
  // Is called on a result, even if it is from overrideResult
86
86
  onResult: ((result: unknown) => MaybePromise<void>)[];
87
+ // IMPORTANT! This is a unique object per connection, reused within the connection. This
88
+ // is allows it to be used as a cache key for connection related info (in a WeakMap).
87
89
  connectionId: { nodeId: string };
88
90
  };
89
91
  export interface SocketFunctionClientHook {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "socket-function",
3
- "version": "0.128.0",
3
+ "version": "0.130.0",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "dependencies": {
package/src/batching.ts CHANGED
@@ -97,10 +97,13 @@ export function batchFunction<Arg, Result = void>(
97
97
  */
98
98
  throttleWindow?: number;
99
99
  name?: string;
100
+ noMeasure?: boolean;
100
101
  },
101
102
  fnc: (arg: Arg[]) => (Promise<Result> | Result)
102
103
  ): (arg: Arg) => Promise<Result> {
103
- fnc = measureWrap(fnc, config.name);
104
+ if (!config.noMeasure) {
105
+ fnc = measureWrap(fnc, config.name);
106
+ }
104
107
 
105
108
  let prevPromise: Promise<Result> | undefined;
106
109
  let batching: {
@@ -171,7 +174,7 @@ export function batchFunction<Arg, Result = void>(
171
174
  export function runInSerial<T extends (...args: any[]) => Promise<any>>(fnc: T): T {
172
175
  let updateQueue: { promise: Promise<void>; resolve: () => void; }[] = [];
173
176
 
174
- return (async (...args: any[]) => {
177
+ return (async function runInSerial(...args: any[]) {
175
178
  let promise = {
176
179
  promise: null as any as Promise<void>,
177
180
  resolve: () => { },
package/src/caching.ts CHANGED
@@ -263,7 +263,7 @@ export function cacheArgsEqual<Fnc extends AnyFunction>(
263
263
  fnc: Fnc,
264
264
  limit = 10
265
265
  ): Fnc & { clear(...args: Args<Fnc>): void } {
266
- let cache = cacheArrayEqual((args: unknown[]) => {
266
+ let cache = cacheArrayEqual(function cacheArgsEqual(args: unknown[]) {
267
267
  return fnc(...args);
268
268
  }, limit);
269
269
  return Object.assign(
@@ -3,7 +3,7 @@ import { CallerContext, CallType, ClientHookContext, FullCallType, FunctionFlags
3
3
  import { _setSocketContext } from "../SocketFunction";
4
4
  import { entries, isNode } from "./misc";
5
5
  import debugbreak from "debugbreak";
6
- import { measureWrap } from "./profiling/measure";
6
+ import { measureBlock, measureWrap } from "./profiling/measure";
7
7
  import { formatTime } from "./formatting/format";
8
8
 
9
9
  let classes: {
@@ -146,7 +146,9 @@ export const runClientHooks = measureWrap(async function runClientHooks(
146
146
  }
147
147
  for (let hook of clientHooks) {
148
148
  let time = Date.now();
149
- await hook(context);
149
+ await measureBlock(async () => {
150
+ await hook(context);
151
+ }, `clientHook|${hook.name || hook.toString().slice(0, 100)}`);
150
152
  time = Date.now() - time;
151
153
  if (time > 500) {
152
154
  console.warn(`Slow (${formatTime(time)}) client hook: ${JSON.stringify(hook.name || hook.toString().slice(0, 100))} for ${callType.classGuid}.${callType.functionName}(...)`);
package/src/misc.ts CHANGED
@@ -196,7 +196,6 @@ export function promiseObj<T = void>(): PromiseObj<T> {
196
196
  return new PromiseObj<T>();
197
197
  }
198
198
 
199
-
200
199
  // Allows an immediate call, then delays the next call until the first call finishes + delay
201
200
  // - Drops all but the latest call, but only resolves the promises return to all
202
201
  // calls once the latest call finishes.
@@ -347,7 +346,8 @@ export function binarySearchBasic<T, V>(array: T[], getVal: (val: T) => V, searc
347
346
  * NOTE: If there are duplicates, returns the first match.
348
347
  *
349
348
  * NOTE: If the value can't be found, returns the bitwise negation of the index where it should be inserted.
350
- * - If you just want the index which is >=, use `if(index < 0) index = ~index;`
349
+ *
350
+ * NOTE: With `if (index < 0) index = ~index;` you will get an index of the value >= the target value.
351
351
  */
352
352
  export function binarySearchIndex(listCount: number, compare: (lhsIndex: number) => number): number {
353
353
  if (listCount === 0) {
@@ -4,9 +4,6 @@ import { isNode } from "../misc";
4
4
  // for use on machines without the ability to compile?
5
5
  //import { now } from "rdtsc-now";
6
6
  let now = () => performance.now();
7
- if (isNode()) {
8
- now = () => performance.now();
9
- }
10
7
 
11
8
  export type OwnTimeObj = {
12
9
  name: string;
@@ -86,6 +86,9 @@ export function registerMeasureInfo(getInfo: () => string | undefined) {
86
86
  extraInfoGetters.push(getInfo);
87
87
  }
88
88
 
89
+ /** IMPORTANT! Always finish the profile! If you don't, you will leak A LOT of memory
90
+ * (you leak all future measures, PER unfinished profile)!
91
+ */
89
92
  export function startMeasure(): {
90
93
  finish: () => MeasureProfile;
91
94
  } {
@@ -101,6 +104,9 @@ export function startMeasure(): {
101
104
  let openAtStart = new Set(getOpenTimesBase());
102
105
 
103
106
  outstandingProfiles.push(profile);
107
+ if (outstandingProfiles.length > 1000) {
108
+ console.warn(red(`You have ${outstandingProfiles.length} outstanding startMeasure calls. You are probably leaking them!`));
109
+ }
104
110
  return {
105
111
  finish() {
106
112
  let pending = getOpenTimesBase();
@@ -157,8 +163,8 @@ export function logMeasureTable(
157
163
  config?: LogMeasureTableConfig
158
164
  ): FormattedMeasureTable | undefined {
159
165
  let { useTotalTime, name } = config || {};
160
- const thresholdInTable = config?.thresholdInTable ?? 0.05;
161
- let minTimeToLog = config?.minTimeToLog ?? 50;
166
+ const thresholdInTable = config?.thresholdInTable ?? 0.02;
167
+ let minTimeToLog = config?.minTimeToLog ?? 20;
162
168
  const maxTableEntries = config?.maxTableEntries ?? 10;
163
169
 
164
170
  function getTime(entry: ProfileEntry) {
@@ -349,6 +355,7 @@ interface ProfileEntry {
349
355
  let measurementsEnabled = true;
350
356
 
351
357
  let outstandingProfiles: MeasureProfile[] = [];
358
+ (globalThis as any).outstandingProfiles = outstandingProfiles;
352
359
  function recordOwnTime(ownTimeObj: OwnTimeObj) {
353
360
  if (outstandingProfiles.length === 0) return;
354
361
  for (let i = 0; i < outstandingProfiles.length; i++) {
@@ -54,7 +54,8 @@ export function getTrueTime() {
54
54
  export function getTrueTimeOffset() {
55
55
  return trueTimeOffset;
56
56
  }
57
- export function waitForFirstTimeSync() {
57
+ export function waitForFirstTimeSync(): Promise<void> | undefined {
58
+ if (didFirstTimeSync) return undefined;
58
59
  return firstTimeSyncPromise;
59
60
  }
60
61
  let shimmed = false;