effectweb 0.3.1 → 0.4.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 (58) hide show
  1. package/README.md +35 -4
  2. package/dist/AsyncContent.d.ts +1 -1
  3. package/dist/AsyncContent.js +18 -35
  4. package/dist/cache.d.ts +2 -2
  5. package/dist/cache.js +7 -3
  6. package/dist/collection.d.ts +1 -1
  7. package/dist/collection.js +1 -3
  8. package/dist/component.js +5 -2
  9. package/dist/dom.d.ts +26 -23
  10. package/dist/dom.js +150 -119
  11. package/dist/effectEvent.d.ts +3 -3
  12. package/dist/effectEvent.js +27 -39
  13. package/dist/form.d.ts +2 -1
  14. package/dist/http.d.ts +2 -1
  15. package/dist/http.js +1 -1
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.js +1 -1
  18. package/dist/infinite-query.d.ts +1 -1
  19. package/dist/infinite-query.js +1 -1
  20. package/dist/jsx-runtime.d.ts +6 -0
  21. package/dist/jsx-runtime.js +14 -1
  22. package/dist/jsx.d.ts +2 -1
  23. package/dist/keyed-tasks.d.ts +5 -4
  24. package/dist/keyed-tasks.js +27 -22
  25. package/dist/lazy.d.ts +2 -1
  26. package/dist/lazy.js +13 -8
  27. package/dist/load.d.ts +1 -1
  28. package/dist/load.js +1 -1
  29. package/dist/mount.d.ts +12 -3
  30. package/dist/mount.js +63 -20
  31. package/dist/owner.d.ts +8 -6
  32. package/dist/owner.js +22 -40
  33. package/dist/pages.d.ts +1 -1
  34. package/dist/pages.js +2 -1
  35. package/dist/program.d.ts +7 -5
  36. package/dist/program.js +33 -20
  37. package/dist/query-internals.d.ts +1 -1
  38. package/dist/query.d.ts +1 -1
  39. package/dist/query.js +0 -2
  40. package/dist/resource.js +3 -1
  41. package/dist/runtime.d.ts +2 -1
  42. package/dist/runtime.js +3 -1
  43. package/dist/session.js +10 -3
  44. package/dist/settlement.d.ts +2 -1
  45. package/dist/settlement.js +13 -8
  46. package/dist/snapshot.d.ts +1 -1
  47. package/dist/snapshot.js +10 -12
  48. package/dist/task.d.ts +1 -1
  49. package/dist/task.js +3 -1
  50. package/dist/tasks.d.ts +1 -1
  51. package/dist/tasks.js +2 -1
  52. package/dist/testing.d.ts +5 -4
  53. package/dist/testing.js +4 -2
  54. package/package.json +1 -1
  55. package/dist/intrinsic.d.ts +0 -2
  56. package/dist/intrinsic.js +0 -120
  57. package/dist/slotIdentity.d.ts +0 -1
  58. package/dist/slotIdentity.js +0 -2
package/dist/program.js CHANGED
@@ -1,9 +1,12 @@
1
1
  import { protectSnapshot } from './snapshot.js';
2
2
  import { reportError, reportSafely } from './errors.js';
3
3
  import { traceProgram, nextProgramId, hasProgramObservers } from './diagnostics.js';
4
- import { Cause, Effect, Fiber, Option, Stream } from 'effect';
4
+ import * as Cause from 'effect/Cause';
5
+ import * as Effect from 'effect/Effect';
6
+ import * as Fiber from 'effect/Fiber';
7
+ import * as Option from 'effect/Option';
8
+ import * as Stream from 'effect/Stream';
5
9
  export const commandSlot = (name) => Symbol(name);
6
- const taskPolicies = ['replace', 'drop', 'parallel', 'queue', 'latest-queued'];
7
10
  /** A lazy request settles successes, typed failures and defects through one message contract. */
8
11
  export function effectCommand(slot, load, handlers) {
9
12
  return {
@@ -68,13 +71,20 @@ export function program(options) {
68
71
  const notifyStopped = () => {
69
72
  if (live.size || running.size || draining)
70
73
  return;
71
- for (const done of stopped)
72
- done();
74
+ const completed = [...stopped];
73
75
  stopped.clear();
76
+ for (const done of completed)
77
+ done();
74
78
  };
75
- const awaitStopped = () => live.size === 0 && running.size === 0 && !draining
76
- ? Promise.resolve()
77
- : new Promise((done) => stopped.add(done));
79
+ const awaitStopped = () => Effect.callback((resume) => {
80
+ if (live.size === 0 && running.size === 0 && !draining)
81
+ return resume(Effect.void);
82
+ const done = () => resume(Effect.void);
83
+ stopped.add(done);
84
+ return Effect.sync(() => {
85
+ stopped.delete(done);
86
+ });
87
+ });
78
88
  let disposed = false;
79
89
  let draining = false;
80
90
  const queue = [];
@@ -146,9 +156,12 @@ export function program(options) {
146
156
  task.fiber = fiber;
147
157
  fiber.addObserver((exit) => {
148
158
  live.delete(task);
149
- notifyStopped();
150
- if (!valid())
159
+ if (!valid()) {
160
+ if (exit._tag === 'Failure' && !Cause.hasInterruptsOnly(exit.cause))
161
+ reportSafely(options.onDefect ?? reportError, exit.cause);
162
+ notifyStopped();
151
163
  return;
164
+ }
152
165
  group.active.delete(task);
153
166
  if (!group.active.size && !group.pending.length)
154
167
  running.delete(command.slot);
@@ -198,10 +211,6 @@ export function program(options) {
198
211
  }
199
212
  const { message } = queue.shift();
200
213
  const transition = options.update(current, message);
201
- for (const command of transition.commands ?? []) {
202
- if (typeof command.slot !== 'symbol' || !taskPolicies.includes(command.policy))
203
- throw new TypeError('Commands require a commandSlot() token and an explicit concurrency policy.');
204
- }
205
214
  trace('update', undefined, message);
206
215
  for (const slot of transition.cancel ?? [])
207
216
  cancel(slot);
@@ -276,17 +285,21 @@ export function program(options) {
276
285
  };
277
286
  return {
278
287
  awaitStopped,
279
- close: () => {
288
+ close: () => Effect.suspend(() => {
280
289
  dispose();
281
290
  return awaitStopped();
282
- },
291
+ }),
283
292
  model: () => current,
284
293
  activeSlots: () => [...running.keys()],
285
- awaitIdle: (slot) => disposed || (!draining && (slot ? !running.has(slot) : running.size === 0))
286
- ? Promise.resolve()
287
- : new Promise((done) => {
288
- waiters.add({ slot, done });
289
- }),
294
+ awaitIdle: (slot) => Effect.callback((resume) => {
295
+ if (disposed || (!draining && (slot ? !running.has(slot) : running.size === 0)))
296
+ return resume(Effect.void);
297
+ const waiter = { slot, done: () => resume(Effect.void) };
298
+ waiters.add(waiter);
299
+ return Effect.sync(() => {
300
+ waiters.delete(waiter);
301
+ });
302
+ }),
290
303
  send,
291
304
  subscribe(listener) {
292
305
  if (disposed)
@@ -1,4 +1,4 @@
1
- import type { Effect } from 'effect';
1
+ import type * as Effect from 'effect/Effect';
2
2
  import type { Snapshot } from './snapshot.js';
3
3
  import type { Query, QueryGroup } from './query.js';
4
4
  export interface QueryDefinition<Args, A, E, R> {
package/dist/query.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Effect } from 'effect';
1
+ import type * as Effect from 'effect/Effect';
2
2
  import { type QueryDefinition } from './query-internals.js';
3
3
  /** Canonical data identity: plain objects, dense arrays, and finite scalar values. */
4
4
  export type QueryKey = string | number | boolean | null | undefined | readonly QueryKey[] | {
package/dist/query.js CHANGED
@@ -54,8 +54,6 @@ export function encodeQueryKey(key) {
54
54
  return encode(key);
55
55
  }
56
56
  export function query(definition) {
57
- if ('key' in definition)
58
- throw new TypeError('Query identity includes all arguments. Remove key and provide services through the Effect environment.');
59
57
  const staleTime = definition.staleTime ?? Infinity;
60
58
  if (Number.isNaN(staleTime) || staleTime < 0)
61
59
  throw new RangeError('Query staleTime must be nonnegative.');
package/dist/resource.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import { commandSlot } from './program.js';
2
- import { Cause, Effect, Option } from 'effect';
2
+ import * as Cause from 'effect/Cause';
3
+ import * as Effect from 'effect/Effect';
4
+ import * as Option from 'effect/Option';
3
5
  import * as AsyncResult from 'effect/unstable/reactivity/AsyncResult';
4
6
  import { loadEffect } from './load.js';
5
7
  import { component } from './component.js';
package/dist/runtime.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { Snapshot } from './snapshot.js';
2
- import { Context, Effect } from 'effect';
2
+ import * as Context from 'effect/Context';
3
+ import * as Effect from 'effect/Effect';
3
4
  import { type Command, type RunningProgram, type Transition } from './program.js';
4
5
  /** A binding to application-owned services, not a new scope or service lifetime. */
5
6
  export interface UiRuntime<R> {
package/dist/runtime.js CHANGED
@@ -1,4 +1,6 @@
1
- import { Context, Effect, Stream } from 'effect';
1
+ import * as Context from 'effect/Context';
2
+ import * as Effect from 'effect/Effect';
3
+ import * as Stream from 'effect/Stream';
2
4
  import { program } from './program.js';
3
5
  export function uiRuntime(context) {
4
6
  const provide = (effect) => Effect.provideContext(effect, context);
package/dist/session.js CHANGED
@@ -192,10 +192,17 @@ export function projectionCache() {
192
192
  }
193
193
  export function sessionGroup(sessions, changed) {
194
194
  const scope = lifetime();
195
- for (const session of sessions) {
195
+ for (const session of sessions)
196
196
  scope.add(() => session.dispose());
197
- if (session.subscribe)
198
- scope.add(session.subscribe(changed));
197
+ try {
198
+ for (const session of sessions) {
199
+ if (session.subscribe)
200
+ scope.add(session.subscribe(changed));
201
+ }
202
+ }
203
+ catch (error) {
204
+ scope.dispose();
205
+ throw error;
199
206
  }
200
207
  return {
201
208
  refresh: () => {
@@ -3,5 +3,6 @@ export declare class Settlement {
3
3
  private pending;
4
4
  private waiters;
5
5
  begin(): () => void;
6
- wait(): Promise<void>;
6
+ wait(): Effect.Effect<void>;
7
7
  }
8
+ import * as Effect from 'effect/Effect';
@@ -1,7 +1,7 @@
1
1
  /** Internal completion accounting, including reentrant acquisition before a fiber is available. */
2
2
  export class Settlement {
3
3
  pending = 0;
4
- waiters = [];
4
+ waiters = new Set();
5
5
  begin() {
6
6
  this.pending++;
7
7
  let finished = false;
@@ -11,17 +11,22 @@ export class Settlement {
11
11
  finished = true;
12
12
  if (--this.pending)
13
13
  return;
14
- for (const done of this.waiters)
14
+ const waiters = [...this.waiters];
15
+ this.waiters.clear();
16
+ for (const done of waiters)
15
17
  done();
16
- this.waiters.length = 0;
17
18
  };
18
19
  }
19
20
  wait() {
20
- return new Promise((done) => {
21
- if (this.pending)
22
- this.waiters.push(done);
23
- else
24
- done();
21
+ return Effect.callback((resume) => {
22
+ if (!this.pending)
23
+ return resume(Effect.void);
24
+ const done = () => resume(Effect.void);
25
+ this.waiters.add(done);
26
+ return Effect.sync(() => {
27
+ this.waiters.delete(done);
28
+ });
25
29
  });
26
30
  }
27
31
  }
32
+ import * as Effect from 'effect/Effect';
@@ -1,4 +1,4 @@
1
- import type { Effect } from 'effect';
1
+ import type * as Effect from 'effect/Effect';
2
2
  import type * as AsyncResult from 'effect/unstable/reactivity/AsyncResult';
3
3
  /** Mark an application service as opaque to snapshot typing; this is a type-only brand. */
4
4
  export declare const snapshotOpaque: unique symbol;
package/dist/snapshot.js CHANGED
@@ -1,19 +1,19 @@
1
1
  import { isAsyncResult } from 'effect/unstable/reactivity/AsyncResult';
2
- const checked = new WeakSet();
2
+ const protectedValues = new WeakSet();
3
3
  /** Protect published plain data in every build. Opaque objects keep their own lifecycle. */
4
4
  export function protectSnapshot(value) {
5
5
  const seen = new Set();
6
6
  const plain = [];
7
- const validate = (item) => {
8
- if (!item || typeof item !== 'object' || checked.has(item) || seen.has(item))
7
+ const visit = (item) => {
8
+ if (!item || typeof item !== 'object' || protectedValues.has(item) || seen.has(item))
9
9
  return;
10
10
  seen.add(item);
11
11
  // Effect wrappers remain opaque, but their successful UI data is plain data.
12
12
  if (isAsyncResult(item)) {
13
13
  if (item._tag === 'Success')
14
- validate(item.value);
14
+ visit(item.value);
15
15
  else if (item._tag === 'Failure' && item.previousSuccess._tag === 'Some')
16
- validate(item.previousSuccess.value);
16
+ visit(item.previousSuccess.value);
17
17
  return;
18
18
  }
19
19
  const prototype = Object.getPrototypeOf(item);
@@ -21,18 +21,16 @@ export function protectSnapshot(value) {
21
21
  return;
22
22
  for (const key of Reflect.ownKeys(item)) {
23
23
  const descriptor = Object.getOwnPropertyDescriptor(item, key);
24
- if (!Object.hasOwn(descriptor, 'value'))
25
- throw new Error(`Snapshot data cannot contain an accessor (${String(key)}). Materialize its value before publication; keep services in opaque instances.`);
26
- validate(descriptor.value);
24
+ if (Object.hasOwn(descriptor, 'value'))
25
+ visit(descriptor.value);
27
26
  }
28
27
  plain.push(item);
29
28
  };
30
- // Validate the complete graph before caching any proof. A rejected cyclic graph
31
- // must not make a later publication skip validation through a previously seen child.
32
- validate(value);
29
+ // Traverse stored data without invoking application getters.
30
+ visit(value);
33
31
  for (const item of plain)
34
32
  Object.freeze(item);
35
33
  for (const item of seen)
36
- checked.add(item);
34
+ protectedValues.add(item);
37
35
  return value;
38
36
  }
package/dist/task.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { Snapshot } from './snapshot.js';
2
- import { Effect } from 'effect';
2
+ import * as Effect from 'effect/Effect';
3
3
  import * as AsyncResult from 'effect/unstable/reactivity/AsyncResult';
4
4
  import type { View } from './dom.js';
5
5
  import { type Send, type TaskPolicy } from './program.js';
package/dist/task.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import { commandSlot } from './program.js';
2
- import { Cause, Effect, Option } from 'effect';
2
+ import * as Cause from 'effect/Cause';
3
+ import * as Effect from 'effect/Effect';
4
+ import * as Option from 'effect/Option';
3
5
  import * as AsyncResult from 'effect/unstable/reactivity/AsyncResult';
4
6
  import { programView } from './component.js';
5
7
  import { effectCommand, } from './program.js';
package/dist/tasks.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { Snapshot } from './snapshot.js';
2
2
  import type { ModelOwner, TaskPolicy } from './owner.js';
3
- import { Effect } from 'effect';
3
+ import * as Effect from 'effect/Effect';
4
4
  import * as AsyncResult from 'effect/unstable/reactivity/AsyncResult';
5
5
  import type { View } from './dom.js';
6
6
  import { type CommandSlot, type Send, type RunningProgram } from './program.js';
package/dist/tasks.js CHANGED
@@ -1,4 +1,5 @@
1
- import { Effect, Option } from 'effect';
1
+ import * as Effect from 'effect/Effect';
2
+ import * as Option from 'effect/Option';
2
3
  import * as AsyncResult from 'effect/unstable/reactivity/AsyncResult';
3
4
  import { programView } from './component.js';
4
5
  import { commandSlot, effectCommand, program, } from './program.js';
package/dist/testing.d.ts CHANGED
@@ -1,12 +1,13 @@
1
- import { Effect } from 'effect';
1
+ import * as Effect from 'effect/Effect';
2
2
  import type { CommandSlot, Program, RunningProgram } from './program.js';
3
3
  import { type UiRuntime } from './runtime.js';
4
4
  /** Program inspection and controlled Effect execution with application-owned services. */
5
5
  export interface ProgramDriver<M, Msg, R = never> extends Program<M, Msg> {
6
+ readonly close: RunningProgram<M, Msg>['close'];
6
7
  readonly activeSlots: RunningProgram<M, Msg>['activeSlots'];
7
- readonly awaitSlot: (slot: CommandSlot) => Promise<void>;
8
- readonly awaitIdle: () => Promise<void>;
9
- readonly run: <A, E>(effect: Effect.Effect<A, E, R>) => Promise<A>;
8
+ readonly awaitSlot: (slot: CommandSlot) => Effect.Effect<void>;
9
+ readonly awaitIdle: () => Effect.Effect<void>;
10
+ readonly run: <A, E>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E>;
10
11
  }
11
12
  export declare function programDriver<M, Msg>(source: RunningProgram<M, Msg>): ProgramDriver<M, Msg>;
12
13
  export declare function programDriver<M, Msg, R>(source: RunningProgram<M, Msg>, runtime: UiRuntime<R>): ProgramDriver<M, Msg, R>;
package/dist/testing.js CHANGED
@@ -1,4 +1,5 @@
1
- import { Cause, Effect } from 'effect';
1
+ import * as Cause from 'effect/Cause';
2
+ import * as Effect from 'effect/Effect';
2
3
  import { defaultUiRuntime } from './runtime.js';
3
4
  export function programDriver(source, runtime) {
4
5
  return makeDriver(source, runtime ?? defaultUiRuntime);
@@ -9,10 +10,11 @@ function makeDriver(source, runtime) {
9
10
  send: source.send,
10
11
  subscribe: source.subscribe,
11
12
  dispose: source.dispose,
13
+ close: source.close,
12
14
  activeSlots: source.activeSlots,
13
15
  awaitSlot: (slot) => source.awaitIdle(slot),
14
16
  awaitIdle: () => source.awaitIdle(),
15
- run: (effect) => Effect.runPromise(runtime.provide(effect)),
17
+ run: runtime.provide,
16
18
  };
17
19
  }
18
20
  /** A reusable controlled request, with cancellation visible to tests. No renderer or private messages. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "effectweb",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Immutable Effect models and compiled JSX with direct DOM rendering",
5
5
  "homepage": "https://github.com/DerpyCrabs/EffectWeb",
6
6
  "bugs": {
@@ -1,2 +0,0 @@
1
- /** Preserve receiver identity and JavaScript call/optional-chain semantics. */
2
- export declare function intrinsic<T>(receiver: T, path: readonly (string | null)[], method: string): T;
package/dist/intrinsic.js DELETED
@@ -1,120 +0,0 @@
1
- import { compiledSlots } from './slotIdentity.js';
2
- // Compiler implementation detail. An untyped receiver's method name is not
3
- // evidence that it is a standard data operation. Validate its descriptor before
4
- // invoking it, without running a user getter in the process.
5
- const prototypes = [
6
- Array.prototype,
7
- String.prototype,
8
- Number.prototype,
9
- Boolean.prototype,
10
- BigInt.prototype,
11
- Function.prototype,
12
- Date.prototype,
13
- RegExp.prototype,
14
- Map.prototype,
15
- Set.prototype,
16
- URL.prototype,
17
- URLSearchParams.prototype,
18
- Blob.prototype,
19
- File.prototype,
20
- Object.getPrototypeOf(Uint8Array.prototype),
21
- Intl.DateTimeFormat.prototype,
22
- Intl.NumberFormat.prototype,
23
- Intl.Collator.prototype,
24
- Intl.RelativeTimeFormat.prototype,
25
- Intl.PluralRules.prototype,
26
- Intl.ListFormat.prototype,
27
- Intl.Segmenter.prototype,
28
- ];
29
- const operations = new Map();
30
- for (const prototype of prototypes) {
31
- for (const [name, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(prototype))) {
32
- if (name === 'constructor')
33
- continue;
34
- const entries = operations.get(name) ?? [];
35
- entries.push(descriptor);
36
- operations.set(name, entries);
37
- }
38
- }
39
- /** Preserve receiver identity and JavaScript call/optional-chain semantics. */
40
- export function intrinsic(receiver, path, method) {
41
- checkPath(receiver, path, 0, method);
42
- return receiver;
43
- }
44
- function checkPath(target, path, index, method) {
45
- if (target === null || target === undefined)
46
- return;
47
- if (index === path.length) {
48
- checkIntrinsic(target, method);
49
- return;
50
- }
51
- const field = path[index];
52
- if (field === null) {
53
- if (Array.isArray(target)) {
54
- for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(target))) {
55
- if (!/^(0|[1-9]\d*)$/u.test(key))
56
- continue;
57
- if (!Object.hasOwn(descriptor, 'value'))
58
- throw new Error('EffectWeb render data cannot use an array accessor. Pass immutable values.');
59
- checkPath(descriptor.value, path, index + 1, method);
60
- }
61
- }
62
- else if (target instanceof Map) {
63
- for (const value of Map.prototype.values.call(target))
64
- checkPath(value, path, index + 1, method);
65
- }
66
- else if (target instanceof Set) {
67
- for (const value of Set.prototype.values.call(target))
68
- checkPath(value, path, index + 1, method);
69
- }
70
- return;
71
- }
72
- let object = Object(target);
73
- while (object) {
74
- const descriptor = Object.getOwnPropertyDescriptor(object, field);
75
- if (descriptor) {
76
- if (Object.hasOwn(descriptor, 'value')) {
77
- checkPath(descriptor.value, path, index + 1, method);
78
- }
79
- else if (descriptor.get &&
80
- operations.get(field)?.some((operation) => operation.get === descriptor.get)) {
81
- // Native getters are checked by identity before execution. File/Blob
82
- // metadata and collection sizes expose data through readonly accessors.
83
- checkPath(descriptor.get.call(target), path, index + 1, method);
84
- }
85
- else {
86
- throw new Error('EffectWeb render data cannot use an accessor to supply a standard data operation. Pass immutable data or a checked helper.');
87
- }
88
- return;
89
- }
90
- object = Object.getPrototypeOf(object);
91
- }
92
- }
93
- function checkIntrinsic(receiver, method) {
94
- if (receiver === null || receiver === undefined)
95
- return;
96
- if (method === '@slot') {
97
- if (typeof receiver !== 'function' || !compiledSlots.has(receiver))
98
- throw new Error('EffectWeb render callbacks must be compiled slots. Declare markup with slot(), or use a checked helper with an explicit purity contract.');
99
- return;
100
- }
101
- let object = Object(receiver);
102
- while (object) {
103
- const descriptor = Object.getOwnPropertyDescriptor(object, method);
104
- if (descriptor) {
105
- const known = operations
106
- .get(method)
107
- ?.some((operation) => Object.hasOwn(descriptor, 'value')
108
- ? typeof descriptor.value === 'function' && descriptor.value === operation.value
109
- : descriptor.get !== undefined &&
110
- descriptor.get === operation.get &&
111
- descriptor.set === undefined);
112
- if (!known)
113
- throw new Error(`EffectWeb cannot prove .${method} is a standard data operation. Use a checked local helper or an imported helper with a purity contract.`);
114
- return;
115
- }
116
- object = Object.getPrototypeOf(object);
117
- }
118
- // The original member call retains its own missing/optional-method behavior.
119
- return;
120
- }
@@ -1 +0,0 @@
1
- export declare const compiledSlots: WeakSet<object>;
@@ -1,2 +0,0 @@
1
- // Shared only by compiler runtime helpers; user functions cannot acquire this proof.
2
- export const compiledSlots = new WeakSet();