@cldmv/slothlet 2.5.5 → 2.6.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.
Files changed (32) hide show
  1. package/README.md +59 -5
  2. package/dist/lib/helpers/als-eventemitter.mjs +5 -4
  3. package/dist/lib/helpers/api_builder.mjs +27 -13
  4. package/dist/lib/helpers/auto-wrap.mjs +4 -2
  5. package/dist/lib/helpers/instance-manager.mjs +111 -0
  6. package/dist/lib/helpers/multidefault.mjs +12 -2
  7. package/dist/lib/modes/slothlet_eager.mjs +1 -1
  8. package/dist/lib/modes/slothlet_lazy.mjs +48 -5
  9. package/dist/lib/runtime/runtime-asynclocalstorage.mjs +435 -0
  10. package/dist/lib/runtime/runtime-livebindings.mjs +298 -0
  11. package/dist/lib/runtime/runtime.mjs +152 -349
  12. package/dist/slothlet.mjs +97 -11
  13. package/index.cjs +30 -39
  14. package/index.mjs +45 -15
  15. package/package.json +17 -1
  16. package/types/dist/lib/helpers/als-eventemitter.d.mts +3 -3
  17. package/types/dist/lib/helpers/als-eventemitter.d.mts.map +1 -1
  18. package/types/dist/lib/helpers/api_builder.d.mts.map +1 -1
  19. package/types/dist/lib/helpers/auto-wrap.d.mts.map +1 -1
  20. package/types/dist/lib/helpers/instance-manager.d.mts +41 -0
  21. package/types/dist/lib/helpers/instance-manager.d.mts.map +1 -0
  22. package/types/dist/lib/helpers/multidefault.d.mts +8 -3
  23. package/types/dist/lib/helpers/multidefault.d.mts.map +1 -1
  24. package/types/dist/lib/modes/slothlet_lazy.d.mts.map +1 -1
  25. package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts +58 -0
  26. package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts.map +1 -0
  27. package/types/dist/lib/runtime/runtime-livebindings.d.mts +58 -0
  28. package/types/dist/lib/runtime/runtime-livebindings.d.mts.map +1 -0
  29. package/types/dist/lib/runtime/runtime.d.mts +8 -57
  30. package/types/dist/lib/runtime/runtime.d.mts.map +1 -1
  31. package/types/dist/slothlet.d.mts +17 -9
  32. package/types/dist/slothlet.d.mts.map +1 -1
@@ -14,411 +14,214 @@
14
14
  limitations under the License.
15
15
  */
16
16
 
17
+ 
17
18
 
18
19
 
19
20
 
21
+ import { detectCurrentInstanceId, getInstanceData } from "../helpers/instance-manager.mjs";
20
22
 
21
- import { AsyncLocalStorage } from "node:async_hooks";
22
- import util from "node:util";
23
- import { enableAlsForEventEmitters } from "@cldmv/slothlet/helpers/als-eventemitter";
24
23
 
25
- const als = new AsyncLocalStorage();
24
+ const asyncRuntime = await import("./runtime-asynclocalstorage.mjs");
25
+ const liveBindingsRuntime = await import("./runtime-livebindings.mjs");
26
26
 
27
27
 
28
- export const sharedALS = new AsyncLocalStorage();
29
-
30
-
31
- enableAlsForEventEmitters(als);
32
-
33
-
34
- export const runWithCtx = (ctx, fn, thisArg, args) => {
28
+ function detectRuntimeType() {
35
29
 
36
- const runtime_runInALS = () => {
37
- const result = Reflect.apply(fn, thisArg, args);
38
- return result;
39
- };
40
- return als.run(ctx, runtime_runInALS);
41
- };
42
-
43
-
44
- export const getCtx = () => als.getStore() || null;
45
-
46
-
47
- const EXCLUDED_CONSTRUCTORS = new Set([Object, Array, Promise, Date, RegExp, Error]);
48
-
49
-
50
- const EXCLUDED_INSTANCEOF_CLASSES = [ArrayBuffer, Map, Set, WeakMap, WeakSet];
51
-
52
-
53
- const PROMISE_METHODS = new Set(["then", "catch", "finally"]);
30
+ const instanceId = detectCurrentInstanceId();
54
31
 
32
+ if (instanceId) {
33
+ const instanceData = getInstanceData(instanceId);
34
+ if (instanceData && instanceData.config && instanceData.config.runtime) {
35
+ return instanceData.config.runtime;
36
+ }
37
+ }
55
38
 
56
- function runtime_shouldWrapMethod(value, prop) {
57
- return (
58
- typeof value === "function" &&
59
- typeof prop === "string" &&
60
- prop !== "constructor" &&
61
- !(prop in Object.prototype) &&
62
- !prop.startsWith("__")
63
- );
39
+
40
+ return "async";
64
41
  }
65
42
 
66
43
 
67
- function runtime_isClassInstance(val) {
68
- if (
69
- val == null ||
70
- typeof val !== "object" ||
71
- !val.constructor ||
72
- typeof val.constructor !== "function" ||
73
- EXCLUDED_CONSTRUCTORS.has(val.constructor)
74
- ) {
75
- return false;
76
- }
77
-
78
- for (const cls of EXCLUDED_INSTANCEOF_CLASSES) {
79
- if (typeof cls === "function" && val instanceof cls) {
80
- return false;
81
- }
82
- }
83
-
84
- return true;
44
+ function getCurrentRuntime() {
45
+ const runtimeType = detectRuntimeType();
46
+ return runtimeType === "live" ? liveBindingsRuntime : asyncRuntime;
85
47
  }
86
48
 
87
49
 
88
- function runtime_wrapClassInstance(instance, ctx, wrapFn, instanceCache) {
89
- if (instanceCache.has(instance)) {
90
- return instanceCache.get(instance);
91
- }
50
+ export const self = new Proxy(
51
+ function runtime_selfProxy() {},
52
+ {
53
+ get(_, prop) {
54
+ const runtime = getCurrentRuntime();
55
+ return runtime.self[prop];
56
+ },
57
+ ownKeys(target) {
58
+ const runtime = getCurrentRuntime();
59
+ const runtimeKeys = Reflect.ownKeys(runtime.self);
60
+ const targetKeys = Reflect.ownKeys(target);
92
61
 
93
-
94
- const methodCache = new Map();
62
+
63
+ const allKeys = new Set([...runtimeKeys, ...targetKeys]);
64
+ return Array.from(allKeys);
65
+ },
66
+ has(_, prop) {
67
+ const runtime = getCurrentRuntime();
68
+ return prop in runtime.self;
69
+ },
70
+ getOwnPropertyDescriptor(target, prop) {
71
+ const runtime = getCurrentRuntime();
72
+ const descriptor = Reflect.getOwnPropertyDescriptor(runtime.self, prop);
95
73
 
96
- const wrappedInstance = new Proxy(instance, {
97
- get(target, prop, receiver) {
98
74
 
99
- if (methodCache.has(prop)) {
100
- return methodCache.get(prop);
75
+ if (!descriptor) {
76
+ return Reflect.getOwnPropertyDescriptor(target, prop);
101
77
  }
102
78
 
103
- const value = Reflect.get(target, prop, receiver);
104
-
105
79
 
106
80
 
107
- if (runtime_shouldWrapMethod(value, prop)) {
81
+ const targetDescriptor = Reflect.getOwnPropertyDescriptor(target, prop);
82
+ if (!targetDescriptor && descriptor && descriptor.configurable === false) {
108
83
 
109
84
 
110
- const runtime_contextPreservingMethod = function (...args) {
111
- const result = runWithCtx(ctx, value, target, args);
112
-
113
- return wrapFn(result);
114
- };
115
-
116
-
117
- methodCache.set(prop, runtime_contextPreservingMethod);
118
- return runtime_contextPreservingMethod;
85
+ return undefined;
119
86
  }
120
87
 
121
-
122
- return wrapFn(value);
88
+ return descriptor;
123
89
  },
124
-
125
- set(target, prop, value, receiver) {
126
-
127
- if (methodCache.has(prop)) {
128
- methodCache.delete(prop);
129
- }
130
- return Reflect.set(target, prop, value, receiver);
131
- }
132
- });
133
-
134
- instanceCache.set(instance, wrappedInstance);
135
- return wrappedInstance;
136
- }
137
-
138
-
139
- export const makeWrapper = (ctx) => {
140
- const cache = new WeakMap();
141
- const instanceCache = new WeakMap();
142
- const promiseMethodCache = new WeakMap();
143
- const wrap = (val) => {
144
- if (val == null || (typeof val !== "object" && typeof val !== "function")) return val;
145
- if (cache.has(val)) return cache.get(val);
146
-
147
- const proxied = new Proxy(val, {
148
- apply(target, thisArg, args) {
149
-
150
-
151
-
152
-
153
-
154
-
155
-
156
-
157
-
158
-
159
-
160
- const result = runWithCtx(ctx, target, thisArg, args);
161
-
162
-
163
- if (runtime_isClassInstance(result)) {
164
- return runtime_wrapClassInstance(result, ctx, wrap, instanceCache);
165
- }
166
-
167
- return result;
168
- },
169
- construct(target, args, newTarget) {
170
-
171
- const result = runWithCtx(ctx, Reflect.construct, undefined, [target, args, newTarget]);
172
-
173
-
174
- if (runtime_isClassInstance(result)) {
175
- return runtime_wrapClassInstance(result, ctx, wrap, instanceCache);
176
- }
177
-
178
- return result;
179
- },
180
- get(target, prop, receiver) {
181
- const value = Reflect.get(target, prop, receiver);
182
-
183
-
184
-
185
- const isPromiseMethod = typeof value === "function" && PROMISE_METHODS.has(prop);
186
- const isNativePromise = util.types.isPromise(target);
187
- const hasThen = typeof target?.then === "function";
188
-
189
- if (isPromiseMethod && (isNativePromise || hasThen)) {
190
-
191
- let targetMethodCache = promiseMethodCache.get(target);
192
- if (!targetMethodCache) {
193
- targetMethodCache = new Map();
194
- promiseMethodCache.set(target, targetMethodCache);
195
- }
196
-
197
- if (targetMethodCache.has(prop)) {
198
- return targetMethodCache.get(prop);
199
- }
200
-
201
- const wrappedMethod = function (...args) {
202
-
203
- const wrappedArgs = args.map((arg) => {
204
- if (typeof arg === "function") {
205
- return function (...callbackArgs) {
206
- return runWithCtx(ctx, arg, undefined, callbackArgs);
207
- };
208
- }
209
- return arg;
210
- });
211
-
212
-
213
- const result = Reflect.apply(value, target, wrappedArgs);
214
-
215
- return wrap(result);
216
- };
217
-
218
- targetMethodCache.set(prop, wrappedMethod);
219
- return wrappedMethod;
220
- }
221
-
222
- return wrap(value);
223
- },
224
- set(target, prop, value, receiver) {
225
-
226
- const methodCache = promiseMethodCache.get(target);
227
- if (methodCache && methodCache.has(prop)) {
228
- methodCache.delete(prop);
229
- }
230
- return Reflect.set(target, prop, value, receiver);
231
- },
232
- defineProperty: Reflect.defineProperty,
233
- deleteProperty(target, prop) {
234
-
235
- const methodCache = promiseMethodCache.get(target);
236
- if (methodCache && methodCache.has(prop)) {
237
- methodCache.delete(prop);
238
- }
239
- return Reflect.deleteProperty(target, prop);
240
- },
241
- ownKeys: Reflect.ownKeys,
242
- getOwnPropertyDescriptor: Reflect.getOwnPropertyDescriptor,
243
- has: Reflect.has
244
- });
245
-
246
- cache.set(val, proxied);
247
- return proxied;
248
- };
249
- return wrap;
250
- };
251
-
252
- function runtime_mutateLiveBinding(target, contextKey) {
253
- const ctx = getCtx();
254
- const source = ctx?.[contextKey];
255
-
256
-
257
- if (!source) {
258
- for (const key of Object.keys(target)) {
259
- if (key !== "_impl") delete target[key];
260
- }
261
- return;
262
- }
263
-
264
- if (typeof source === "function") {
265
-
266
-
267
- const runtime_forwardToSource = (...args) => source(...args);
268
- target._impl = runtime_forwardToSource;
269
-
270
-
271
- for (const key of Object.keys(target)) {
272
- if (key !== "_impl") delete target[key];
273
- }
274
- for (const key of Object.getOwnPropertyNames(source)) {
275
- if (key !== "length" && key !== "name" && key !== "prototype" && key !== "_impl") {
276
- try {
277
- target[key] = source[key];
278
- } catch {
279
-
280
- }
281
- }
282
- }
283
- } else if (typeof source === "object" && source !== null) {
284
-
285
- for (const key of Object.keys(target)) {
286
- if (key !== "_impl") delete target[key];
287
- }
288
- for (const [key, value] of Object.entries(source)) {
289
- target[key] = value;
290
- }
291
- if (typeof source._impl === "function") {
292
- target._impl = source._impl;
90
+ getPrototypeOf() {
91
+ const runtime = getCurrentRuntime();
92
+ return Reflect.getPrototypeOf(runtime.self);
93
+ },
94
+ isExtensible() {
95
+ const runtime = getCurrentRuntime();
96
+ return Reflect.isExtensible(runtime.self);
293
97
  }
294
98
  }
295
- }
296
-
297
-
298
- function runtime_createLiveBinding(contextKey) {
299
-
300
-
301
- function runtime_liveBindingTarget() {}
302
- const liveBinding = runtime_liveBindingTarget;
303
-
304
-
305
- const runtime_syncWithContext = () => runtime_mutateLiveBinding(liveBinding, contextKey);
99
+ );
100
+
101
+ export const context = new Proxy(
102
+ {},
103
+ {
104
+ get(_, prop) {
105
+ const runtime = getCurrentRuntime();
106
+ return runtime.context[prop];
107
+ },
108
+ ownKeys(target) {
109
+ const runtime = getCurrentRuntime();
110
+ const runtimeKeys = Reflect.ownKeys(runtime.context);
111
+ const targetKeys = Reflect.ownKeys(target);
306
112
 
307
-
308
-
309
- const runtime_renderSnapshot = (val) => {
310
- if (typeof val === "function") {
311
- const name = val.name || "anonymous";
312
- const props = {};
313
- for (const k of Object.keys(val)) props[k] = val[k];
314
113
 
315
- return { [`[Function: ${name}]`]: true, ...props };
316
- }
317
- return val;
318
- };
319
-
320
- const proxy = new Proxy(liveBinding, {
321
-
322
- apply(_t, thisArg, args) {
323
- const cur = getCtx()?.[contextKey];
324
- if (typeof cur === "function") {
325
- return Reflect.apply(cur, thisArg, args);
326
- }
327
-
328
- return cur;
114
+ const allKeys = new Set([...runtimeKeys, ...targetKeys]);
115
+ return Array.from(allKeys);
329
116
  },
330
- construct(_t, args, newTarget) {
331
- const cur = getCtx()?.[contextKey];
332
- if (typeof cur === "function") {
333
- return Reflect.construct(cur, args, newTarget);
334
- }
335
- throw new TypeError(`${contextKey} is not a constructor`);
117
+ has(_, prop) {
118
+ const runtime = getCurrentRuntime();
119
+ return prop in runtime.context;
336
120
  },
121
+ getOwnPropertyDescriptor(target, prop) {
122
+ const runtime = getCurrentRuntime();
123
+ const descriptor = Reflect.getOwnPropertyDescriptor(runtime.context, prop);
337
124
 
338
- get(target, prop) {
339
125
 
340
- if (prop === "nonExistentTestProperty") {
341
-
342
-
343
-
344
- return undefined;
126
+ if (!descriptor) {
127
+ return Reflect.getOwnPropertyDescriptor(target, prop);
345
128
  }
346
129
 
347
130
 
348
- if (prop === util.inspect.custom) return runtime_inspectHandler;
349
- if (prop === "toJSON") return runtime_toJSONHandler;
350
- if (prop === "$value") return runtime_toJSONHandler;
351
- if (prop === Symbol.toPrimitive) {
131
+
132
+ const targetDescriptor = Reflect.getOwnPropertyDescriptor(target, prop);
133
+ if (!targetDescriptor && descriptor && descriptor.configurable === false) {
352
134
 
353
- const runtime_toPrimitiveHandler = (hint) => {
354
- const v = getCtx()?.[contextKey];
355
- return hint === "string" ? String(v) : v;
356
- };
357
- return runtime_toPrimitiveHandler;
135
+
136
+ return undefined;
358
137
  }
359
138
 
360
-
361
-
139
+ return descriptor;
140
+ },
141
+ getPrototypeOf() {
142
+ const runtime = getCurrentRuntime();
143
+ return Reflect.getPrototypeOf(runtime.context);
144
+ },
145
+ isExtensible() {
146
+ const runtime = getCurrentRuntime();
147
+ return Reflect.isExtensible(runtime.context);
148
+ }
149
+ }
150
+ );
151
+
152
+ export const reference = new Proxy(
153
+ {},
154
+ {
155
+ get(_, prop) {
156
+ const runtime = getCurrentRuntime();
157
+ return runtime.reference[prop];
158
+ },
159
+ ownKeys(target) {
160
+ const runtime = getCurrentRuntime();
161
+ const runtimeKeys = Reflect.ownKeys(runtime.reference);
162
+ const targetKeys = Reflect.ownKeys(target);
362
163
 
363
164
 
364
- runtime_syncWithContext();
365
- return target[prop];
165
+ const allKeys = new Set([...runtimeKeys, ...targetKeys]);
166
+ return Array.from(allKeys);
167
+ },
168
+ has(_, prop) {
169
+ const runtime = getCurrentRuntime();
170
+ return prop in runtime.reference;
366
171
  },
172
+ getOwnPropertyDescriptor(target, prop) {
173
+ const runtime = getCurrentRuntime();
174
+ const descriptor = Reflect.getOwnPropertyDescriptor(runtime.reference, prop);
367
175
 
368
- set(target, prop, value) {
369
- runtime_syncWithContext();
370
- target[prop] = value;
176
+
177
+ if (!descriptor) {
178
+ return Reflect.getOwnPropertyDescriptor(target, prop);
179
+ }
371
180
 
372
181
 
373
- const ctx = getCtx();
374
- if (ctx && ctx[contextKey] && typeof ctx[contextKey] === "object") {
375
- ctx[contextKey][prop] = value;
182
+
183
+ const targetDescriptor = Reflect.getOwnPropertyDescriptor(target, prop);
184
+ if (!targetDescriptor && descriptor && descriptor.configurable === false) {
185
+
186
+
187
+ return undefined;
376
188
  }
377
- return true;
378
- },
379
189
 
380
- has(target, prop) {
381
- runtime_syncWithContext();
382
- return prop in target;
190
+ return descriptor;
383
191
  },
384
-
385
- ownKeys(target) {
386
- runtime_syncWithContext();
387
- return Reflect.ownKeys(target);
192
+ getPrototypeOf() {
193
+ const runtime = getCurrentRuntime();
194
+ return Reflect.getPrototypeOf(runtime.reference);
388
195
  },
389
-
390
- getOwnPropertyDescriptor(target, prop) {
391
- runtime_syncWithContext();
392
- return Object.getOwnPropertyDescriptor(target, prop);
196
+ isExtensible() {
197
+ const runtime = getCurrentRuntime();
198
+ return Reflect.isExtensible(runtime.reference);
393
199
  }
394
- });
395
-
396
-
397
-
398
- const runtime_inspectHandler = () => runtime_renderSnapshot(getCtx()?.[contextKey]);
399
-
400
-
401
- const runtime_toJSONHandler = () => getCtx()?.[contextKey];
402
-
403
- Object.defineProperty(liveBinding, util.inspect.custom, { value: runtime_inspectHandler, enumerable: false });
404
- Object.defineProperty(liveBinding, "toJSON", { value: runtime_toJSONHandler, enumerable: false });
405
-
406
-
407
-
408
-
200
+ }
201
+ );
409
202
 
410
- return proxy;
203
+ export function runWithCtx(ctx, fn, thisArg, args) {
204
+ const runtime = getCurrentRuntime();
205
+ return runtime.runWithCtx(ctx, fn, thisArg, args);
411
206
  }
412
207
 
208
+ export function makeWrapper(ctx) {
209
+ const runtime = getCurrentRuntime();
210
+ return runtime.makeWrapper(ctx);
211
+ }
413
212
 
213
+ export function getCtx() {
214
+ const runtime = getCurrentRuntime();
215
+ return (runtime.getCtx || runtime.getContext)();
216
+ }
414
217
 
218
+ export const instanceId = (() => {
219
+ const runtimeType = detectRuntimeType();
220
+ if (runtimeType === "async") {
221
+ return null;
222
+ }
223
+ const runtime = getCurrentRuntime();
224
+ return runtime.instanceId;
225
+ })();
415
226
 
416
- export const self = runtime_createLiveBinding("self");
417
-
418
-
419
- export const context = runtime_createLiveBinding("context");
420
-
421
-
422
- export const reference = runtime_createLiveBinding("reference");
423
-
424
-
227
+ export const sharedALS = getCurrentRuntime().sharedALS;