@absolutejs/sync 1.7.4 → 1.7.5

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.
@@ -60,15 +60,17 @@ export type SandboxConfig = {
60
60
  };
61
61
  /**
62
62
  * Build a lazy runner for one mutation's sandboxed source. The first call
63
- * compiles the isolate + context + callable; subsequent calls reuse all
64
- * three and only pack the per-call args (`args`, `ctx`, and a fresh
65
- * dispatch Reference closed over this call's `actions`). If the isolate
66
- * has been disposed (timeout, memory cap), the next call re-spawns
67
- * transparently.
63
+ * compiles the isolate + context + dispatch Reference + callable;
64
+ * subsequent calls only generate a fresh callId, register the per-call
65
+ * `actions` in the callMap, and invoke `callable.call([callId, args,
66
+ * ctx])`. Per-call cost on FFI: one JSObjectCallAsFunction + three
67
+ * cheap primitive packings. No per-call Reference allocation, no
68
+ * setGlobal, no eval.
68
69
  *
69
- * Concurrency-safe by construction: every call gets its own fresh
70
- * dispatch Reference closed over its own `actions`. No shared slot, no
71
- * promise queue needed. (Reference allocation cost is ~0.003 ms per
72
- * call negligible.)
70
+ * Concurrency-safe by construction: each call has its own callId →
71
+ * its own actions slot in the callMap.
72
+ *
73
+ * If the isolate has been disposed (timeout, memory cap), the next
74
+ * call re-spawns transparently.
73
75
  */
74
76
  export declare const makeSandboxedHandler: (source: string, config?: SandboxConfig) => ((args: unknown, ctx: unknown, actions: MutationActions) => Promise<unknown>);
package/dist/index.js CHANGED
@@ -725,7 +725,7 @@ var loadIsolatedJsc = async () => {
725
725
  }
726
726
  };
727
727
  var wrap = (source) => `
728
- function (args, ctx, __dispatch) {
728
+ function (__callId, args, ctx) {
729
729
  const userFn = (${source});
730
730
  if (typeof userFn !== 'function') {
731
731
  throw new Error(
@@ -734,26 +734,48 @@ var wrap = (source) => `
734
734
  );
735
735
  }
736
736
  const actions = {
737
- insert: (table, data) => __dispatch('insert', table, data),
738
- update: (table, data) => __dispatch('update', table, data),
739
- delete: (table, row) => __dispatch('delete', table, row),
740
- change: (collection, change) => __dispatch('change', collection, change)
737
+ insert: (table, data) => __dispatch(__callId, 'insert', table, data),
738
+ update: (table, data) => __dispatch(__callId, 'update', table, data),
739
+ delete: (table, row) => __dispatch(__callId, 'delete', table, row),
740
+ change: (collection, change) => __dispatch(__callId, 'change', collection, change)
741
741
  };
742
742
  return userFn(args, ctx, actions);
743
743
  }
744
744
  `;
745
745
  var compile = async (source, config) => {
746
- const { createIsolate } = await loadIsolatedJsc();
746
+ const { createIsolate, Reference } = await loadIsolatedJsc();
747
747
  const isolate = await createIsolate({
748
748
  backend: config.backend ?? "auto",
749
749
  memoryLimit: config.memoryLimit ?? 32
750
750
  });
751
751
  const context = await isolate.createContext();
752
+ const callMap = new Map;
753
+ const dispatch = new Reference((callId, op, ...rest) => {
754
+ const a = callMap.get(callId);
755
+ if (a === undefined) {
756
+ throw new Error(`__dispatch invoked for orphan callId ${String(callId)}`);
757
+ }
758
+ switch (op) {
759
+ case "insert":
760
+ return a.insert(rest[0], rest[1]);
761
+ case "update":
762
+ return a.update(rest[0], rest[1]);
763
+ case "delete":
764
+ return a.delete(rest[0], rest[1]);
765
+ case "change":
766
+ return a.change(rest[0], rest[1]);
767
+ default:
768
+ throw new Error(`unknown sandbox action op: ${String(op)}`);
769
+ }
770
+ });
771
+ await context.setGlobal("__dispatch", dispatch);
752
772
  const callable = await context.compileCallable(wrap(source));
753
773
  return {
754
774
  callable,
775
+ callMap,
755
776
  context,
756
777
  isolate,
778
+ nextCallId: 1,
757
779
  timeoutMs: config.timeout ?? 5000
758
780
  };
759
781
  };
@@ -770,25 +792,16 @@ var makeSandboxedHandler = (source, config = {}) => {
770
792
  return pending;
771
793
  };
772
794
  return async (args, ctx, actions) => {
773
- const { Reference } = await loadIsolatedJsc();
774
795
  const compiled = await getCompiled();
775
- const dispatch = new Reference((op, ...rest) => {
776
- switch (op) {
777
- case "insert":
778
- return actions.insert(rest[0], rest[1]);
779
- case "update":
780
- return actions.update(rest[0], rest[1]);
781
- case "delete":
782
- return actions.delete(rest[0], rest[1]);
783
- case "change":
784
- return actions.change(rest[0], rest[1]);
785
- default:
786
- throw new Error(`unknown sandbox action op: ${String(op)}`);
787
- }
788
- });
789
- return compiled.callable.call([args, ctx, dispatch], {
790
- timeout: compiled.timeoutMs
791
- });
796
+ const callId = compiled.nextCallId++;
797
+ compiled.callMap.set(callId, actions);
798
+ try {
799
+ return await compiled.callable.call([callId, args, ctx], {
800
+ timeout: compiled.timeoutMs
801
+ });
802
+ } finally {
803
+ compiled.callMap.delete(callId);
804
+ }
792
805
  };
793
806
  };
794
807
 
@@ -2310,5 +2323,5 @@ export {
2310
2323
  createPresenceHub
2311
2324
  };
2312
2325
 
2313
- //# debugId=E4BD5E29981CFB6664756E2164756E21
2326
+ //# debugId=B9056CA0A3DAE81164756E2164756E21
2314
2327
  //# sourceMappingURL=index.js.map