functionalscript 0.46.0 → 0.47.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 (178) hide show
  1. package/fjs/basen/cbase32/module.f.mjs +18 -10
  2. package/fjs/basen/cbase32/proof.f.d.mts +3 -0
  3. package/fjs/basen/cbase32/proof.f.mjs +24 -2
  4. package/fjs/basen/proof.f.mjs +8 -16
  5. package/fjs/bnf/ll1/proof.f.d.mts +2 -0
  6. package/fjs/bnf/ll1/proof.f.mjs +33 -18
  7. package/fjs/bnf/module.f.d.mts +2 -2
  8. package/fjs/bnf/module.f.mjs +2 -2
  9. package/fjs/cas/proof.f.mjs +4 -26
  10. package/fjs/ci/common/module.f.mjs +6 -0
  11. package/fjs/ci/config/module.f.d.mts +7 -7
  12. package/fjs/ci/config/module.f.mjs +7 -7
  13. package/fjs/cli/module.f.mjs +14 -10
  14. package/fjs/crypto/vdf/module.f.d.mts +0 -1
  15. package/fjs/crypto/vdf/module.f.mjs +3 -14
  16. package/fjs/dev/module.f.mjs +10 -20
  17. package/fjs/djs/parser/module.f.d.mts +101 -53
  18. package/fjs/djs/parser/module.f.mjs +732 -525
  19. package/fjs/djs/parser/proof.f.d.mts +6 -0
  20. package/fjs/djs/parser/proof.f.mjs +315 -11
  21. package/fjs/djs/parser/types.d.ts +29 -2
  22. package/fjs/djs/tokenizer/module.f.mjs +122 -105
  23. package/fjs/djs/tokenizer/proof.f.mjs +17 -0
  24. package/fjs/djs/transpiler/module.f.mjs +4 -5
  25. package/fjs/djs/transpiler/proof.f.d.mts +2 -0
  26. package/fjs/djs/transpiler/proof.f.mjs +25 -0
  27. package/fjs/edag/amnesia/module.f.d.mts +20 -0
  28. package/fjs/edag/amnesia/module.f.mjs +303 -0
  29. package/fjs/edag/amnesia/proof.f.d.mts +79 -0
  30. package/fjs/edag/amnesia/proof.f.mjs +573 -0
  31. package/fjs/edag/amnesia/types.d.ts +15 -0
  32. package/fjs/edag/module.f.d.mts +410 -0
  33. package/fjs/edag/module.f.mjs +559 -0
  34. package/fjs/edag/proof.f.d.mts +116 -0
  35. package/fjs/edag/proof.f.mjs +686 -0
  36. package/fjs/edag/types.d.ts +55 -0
  37. package/fjs/effects/node/memory/module.d.mts +37 -3
  38. package/fjs/effects/node/memory/module.mjs +38 -4
  39. package/fjs/effects/node/memory/proof.d.mts +5 -2
  40. package/fjs/effects/node/memory/proof.mjs +36 -6
  41. package/fjs/effects/node/module.d.mts +9 -1
  42. package/fjs/effects/node/module.f.d.mts +39 -0
  43. package/fjs/effects/node/module.f.mjs +46 -0
  44. package/fjs/effects/node/module.mjs +234 -32
  45. package/fjs/effects/node/types.d.ts +28 -2
  46. package/fjs/effects/node/virtual/module.f.d.mts +19 -10
  47. package/fjs/effects/node/virtual/module.f.mjs +246 -32
  48. package/fjs/effects/node/virtual/proof.f.d.mts +17 -2
  49. package/fjs/effects/node/virtual/proof.f.mjs +232 -8
  50. package/fjs/effects/node/virtual/types.d.ts +57 -1
  51. package/fjs/emergent_testing/browser/proof.d.mts +55 -0
  52. package/fjs/emergent_testing/browser/proof.mjs +352 -0
  53. package/fjs/emergent_testing/browser/species.proof.d.mts +4 -0
  54. package/fjs/emergent_testing/browser/species.proof.mjs +45 -0
  55. package/fjs/emergent_testing/browser.d.mts +79 -0
  56. package/fjs/emergent_testing/browser.mjs +432 -0
  57. package/fjs/emergent_testing/proof.f.d.mts +1 -1
  58. package/fjs/emergent_testing/proof.f.mjs +2 -2
  59. package/fjs/js/string_escape/module.f.d.mts +47 -0
  60. package/fjs/js/string_escape/module.f.mjs +95 -0
  61. package/fjs/js/string_escape/proof.f.d.mts +8 -0
  62. package/fjs/js/string_escape/proof.f.mjs +68 -0
  63. package/fjs/js/tokenizer/module.f.mjs +14 -12
  64. package/fjs/mcp/cas/module.f.d.mts +1 -7
  65. package/fjs/mcp/cas/module.f.mjs +24 -15
  66. package/fjs/mcp/evo/module.f.mjs +9 -24
  67. package/fjs/mcp/module.f.d.mts +3 -1
  68. package/fjs/mcp/module.f.mjs +4 -2
  69. package/fjs/media/json/rtti/module.f.d.mts +2 -2
  70. package/fjs/media/json/rtti/module.f.mjs +1 -1
  71. package/fjs/media/json/schema/module.f.d.mts +15 -5
  72. package/fjs/media/json/schema/module.f.mjs +42 -15
  73. package/fjs/media/json/schema/proof.f.d.mts +10 -1
  74. package/fjs/media/json/schema/proof.f.mjs +88 -16
  75. package/fjs/media/json/serializer/module.f.mjs +14 -26
  76. package/fjs/media/json/types.d.ts +1 -1
  77. package/fjs/media/lock/module.f.d.mts +8 -3
  78. package/fjs/media/lock/module.f.mjs +9 -3
  79. package/fjs/media/lock/proof.f.d.mts +1 -1
  80. package/fjs/media/lock/proof.f.mjs +2 -2
  81. package/fjs/media/lock/types.d.ts +1 -3
  82. package/fjs/media/module.f.d.mts +20 -13
  83. package/fjs/media/module.f.mjs +29 -16
  84. package/fjs/media/note/module.f.d.mts +14 -7
  85. package/fjs/media/note/module.f.mjs +14 -7
  86. package/fjs/media/note/proof.f.mjs +1 -1
  87. package/fjs/media/proof.f.mjs +5 -5
  88. package/fjs/media/revision/module.f.d.mts +8 -2
  89. package/fjs/media/revision/module.f.mjs +9 -3
  90. package/fjs/media/revision/proof.f.mjs +1 -1
  91. package/fjs/media/revision/types.d.ts +1 -1
  92. package/fjs/media/type/module.f.d.mts +20 -0
  93. package/fjs/media/type/module.f.mjs +74 -0
  94. package/fjs/media/type/proof.f.d.mts +5 -0
  95. package/fjs/media/type/proof.f.mjs +24 -1
  96. package/fjs/module.f.mjs +6 -0
  97. package/fjs/path/module.f.d.mts +60 -3
  98. package/fjs/path/module.f.mjs +138 -14
  99. package/fjs/path/proof.f.d.mts +3 -0
  100. package/fjs/path/proof.f.mjs +298 -2
  101. package/fjs/protocol/json_rpc/module.f.d.mts +65 -28
  102. package/fjs/protocol/json_rpc/module.f.mjs +49 -13
  103. package/fjs/protocol/json_rpc/proof.f.d.mts +4 -0
  104. package/fjs/protocol/json_rpc/proof.f.mjs +29 -0
  105. package/fjs/protocol/json_rpc/types.d.ts +12 -2
  106. package/fjs/protocol/mcp/module.f.d.mts +89 -54
  107. package/fjs/protocol/mcp/module.f.mjs +110 -56
  108. package/fjs/protocol/mcp/proof.f.d.mts +13 -0
  109. package/fjs/protocol/mcp/proof.f.mjs +107 -7
  110. package/fjs/protocol/mcp/stdio/module.f.mjs +3 -4
  111. package/fjs/protocol/mcp/stdio/proof.f.mjs +2 -2
  112. package/fjs/protocol/mcp/types.d.ts +14 -2
  113. package/fjs/text/utf8/module.f.mjs +27 -1
  114. package/fjs/text/utf8/proof.f.mjs +37 -0
  115. package/fjs/types/array/module.f.mjs +18 -11
  116. package/fjs/types/array/proof.f.mjs +27 -1
  117. package/fjs/types/bigfloat/module.f.d.mts +48 -9
  118. package/fjs/types/bigfloat/module.f.mjs +147 -59
  119. package/fjs/types/bigfloat/proof.f.d.mts +2 -0
  120. package/fjs/types/bigfloat/proof.f.mjs +136 -4
  121. package/fjs/types/bigfloat/types.d.ts +17 -0
  122. package/fjs/types/function/module.f.d.mts +11 -2
  123. package/fjs/types/function/module.f.mjs +20 -2
  124. package/fjs/types/function/proof.f.mjs +5 -1
  125. package/fjs/types/phantom/types.d.ts +21 -0
  126. package/fjs/types/result/module.f.d.mts +4 -4
  127. package/fjs/types/result/module.f.mjs +2 -2
  128. package/fjs/types/result/proof.f.d.mts +6 -2
  129. package/fjs/types/result/proof.f.mjs +17 -1
  130. package/fjs/types/rtti/common/module.f.d.mts +78 -5
  131. package/fjs/types/rtti/common/module.f.mjs +168 -3
  132. package/fjs/types/rtti/common/proof.f.d.mts +14 -0
  133. package/fjs/types/rtti/common/proof.f.mjs +61 -2
  134. package/fjs/types/rtti/common/types.d.ts +23 -1
  135. package/fjs/types/rtti/data/module.f.d.mts +57 -1
  136. package/fjs/types/rtti/data/module.f.mjs +241 -47
  137. package/fjs/types/rtti/data/proof.f.d.mts +10 -0
  138. package/fjs/types/rtti/data/proof.f.mjs +272 -39
  139. package/fjs/types/rtti/data/types.d.ts +14 -7
  140. package/fjs/types/rtti/host.proof.d.mts +33 -0
  141. package/fjs/types/rtti/host.proof.mjs +170 -0
  142. package/fjs/types/rtti/module.f.d.mts +51 -6
  143. package/fjs/types/rtti/module.f.mjs +50 -3
  144. package/fjs/types/rtti/parse/module.f.d.mts +31 -24
  145. package/fjs/types/rtti/parse/module.f.mjs +197 -59
  146. package/fjs/types/rtti/parse/proof.f.d.mts +37 -2
  147. package/fjs/types/rtti/parse/proof.f.mjs +171 -47
  148. package/fjs/types/rtti/proof.f.d.mts +6 -0
  149. package/fjs/types/rtti/proof.f.mjs +42 -1
  150. package/fjs/types/rtti/ts/module.f.d.mts +9 -3
  151. package/fjs/types/rtti/ts/module.f.mjs +68 -15
  152. package/fjs/types/rtti/ts/proof.f.d.mts +42 -2
  153. package/fjs/types/rtti/ts/proof.f.mjs +139 -6
  154. package/fjs/types/rtti/ts/types.d.ts +164 -16
  155. package/fjs/types/rtti/types.d.ts +31 -3
  156. package/fjs/types/rtti/validate/module.f.d.mts +120 -0
  157. package/fjs/types/rtti/validate/module.f.mjs +351 -0
  158. package/fjs/types/rtti/validate/proof.f.d.mts +154 -0
  159. package/fjs/types/rtti/validate/proof.f.mjs +781 -0
  160. package/fjs/types/ts/types.d.ts +4 -0
  161. package/fjs/web/module.f.d.mts +115 -0
  162. package/fjs/web/module.f.mjs +581 -0
  163. package/fjs/web/proof.f.d.mts +39 -0
  164. package/fjs/web/proof.f.mjs +413 -0
  165. package/fjs/web/types.d.ts +39 -0
  166. package/fjs/website/browser-prepare.d.mts +5 -0
  167. package/fjs/website/browser-prepare.mjs +115 -0
  168. package/fjs/website/browser-source.d.mts +37 -0
  169. package/fjs/website/browser-source.mjs +202 -0
  170. package/fjs/website/browser-source.proof.d.mts +31 -0
  171. package/fjs/website/browser-source.proof.mjs +162 -0
  172. package/fjs/website/browser.d.mts +5 -0
  173. package/fjs/website/browser.mjs +8 -0
  174. package/fjs/website/module.f.d.mts +3 -3
  175. package/fjs/website/module.f.mjs +62 -9
  176. package/fjs/website/proof.f.d.mts +4 -0
  177. package/fjs/website/proof.f.mjs +18 -3
  178. package/package.json +2 -3
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Type-level API for `fjs/edag/module.f.mjs`: `Exp`, the union of every EDAG
3
+ * node kind — see the union immediately below for the current list, rather
4
+ * than enumerating it here too, where it silently drifts stale as nodes are
5
+ * added — each pinned against its rtti schema in the sibling module with
6
+ * `Assert<Check<..., typeof ...>>`. Every tuple here is closed on both sides:
7
+ * none of the schemas says `open`, so these types are exact rather than the
8
+ * approximation `TupleTs` in `../types/rtti/ts/types.ts` describes.
9
+ */
10
+ export type Exp = Primitive | Array | Object | Dot | Call | OptionDot | OptionCall | Comma | Op2 | Op1 | Op0;
11
+ /**
12
+ * Bare constant values, not operation nodes — `undefined` is deliberately
13
+ * excluded, since `['undefined']` is a tagged `Op0` operation, not a bare
14
+ * value; see `primitive` in `module.f.mjs`.
15
+ */
16
+ export type Primitive = null | boolean | number | string | bigint;
17
+ export type Exps = readonly Exp[];
18
+ export type Spread = readonly ['...', Exp];
19
+ export type Items = Exp | Spread;
20
+ export type Array = readonly ['[]', readonly Items[]];
21
+ export type Property = readonly [':', Exp, Exp];
22
+ export type Properties = Property | Spread;
23
+ export type Object = readonly ['{}', readonly Properties[]];
24
+ export type NumberCast = readonly ['Number', Exp];
25
+ export type Index = number | NumberCast | string;
26
+ /**
27
+ * The continuation of a `Dot`: a receiver is live, no region is open.
28
+ *
29
+ * Only a call can be here — a property step would waste the receiver with no
30
+ * region to keep it in, so `a.b.c` nests `Dot`s instead.
31
+ */
32
+ export type PropertyLambda = null | readonly ['|()', Exp, null] | readonly ['|?.()', Exp, OptionLambda];
33
+ /**
34
+ * The continuation of a step that produced a plain value inside an open
35
+ * region: `OptionCall`'s, and every call step that stays in its region.
36
+ */
37
+ export type OptionLambda = null | readonly ['|()', Exp, OptionLambda] | readonly ['|.', Index, OptionPropertyLambda];
38
+ /**
39
+ * The continuation of a property step inside an open region: both bits live,
40
+ * so this is the state with every production — the three ways a call can
41
+ * relate to the region it sits in, plus the property step the region keeps
42
+ * from leaving.
43
+ */
44
+ export type OptionPropertyLambda = null | readonly ['|()', Exp, OptionLambda] | readonly ['|.', Index, OptionPropertyLambda] | readonly ['|?.()', Exp, OptionLambda] | readonly ['|!()', Exp, null];
45
+ export type Call = readonly ['()', Exp, Exp];
46
+ export type Dot = readonly ['.', Exp, Index, PropertyLambda];
47
+ export type OptionDot = readonly ['?.', Exp, Index, OptionPropertyLambda];
48
+ export type OptionCall = readonly ['?.()', Exp, Exp, OptionLambda];
49
+ export type Comma = readonly [',', Exps];
50
+ export type Op0Id = 'undefined' | 'args' | 'frame';
51
+ export type Op0 = readonly [Op0Id];
52
+ export type Op1Id = 'String' | 'Number' | 'neg' | '!' | '~';
53
+ export type Op1 = readonly [Op1Id, Exp];
54
+ export type Op2Id = '=>' | 'own' | '===' | '!==' | '>' | '>=' | '<' | '<=' | '+' | '-' | '*' | '/' | '%' | '**' | '&' | '|' | '^' | '<<' | '>>' | '>>>' | '&&' | '||' | '??';
55
+ export type Op2 = readonly [Op2Id, Exp, Exp];
@@ -22,8 +22,42 @@ export type Uuid = () => string;
22
22
  * @type {(uuid?: Uuid) => MemoryOperationMap}
23
23
  */
24
24
  export declare const memoryOperationMap: (uuid?: Uuid) => MemoryOperationMap;
25
+ export type MemoryRun = <T, E>(effect: Effect<MemOp, T, E>) => Promise<Result<T, E>>;
25
26
  /**
26
- * Runs a memory-only effect using a fresh memory store.
27
- * @type {<T, E>(effect: Effect<MemOp, T, E>) => Promise<Result<T, E>>}
27
+ * An {@link asyncRun} runner over {@link MemOp}: an effect in, its `Result` out.
28
+ * @typedef {<T, E>(effect: Effect<MemOp, T, E>) => Promise<Result<T, E>>} MemoryRun
28
29
  */
29
- export declare const run: <T, E>(effect: Effect<MemOp, T, E>) => Promise<Result<T, E>>;
30
+ /**
31
+ * Creates a runner owning a fresh memory store. Every effect passed to the
32
+ * *same* runner shares that store; a new runner starts empty.
33
+ *
34
+ * **The `MemoryRun` annotation is what types the `asyncRun` call.** `asyncRun`
35
+ * takes a `ToAsyncOperationMap<O>`, a mapped type keyed on `O[0]`, and
36
+ * TypeScript cannot infer `O` back out of one — only a homomorphic
37
+ * `{[K in keyof T]: …}` is reversed. Left to argument inference `O` falls back
38
+ * to its `Operation` constraint, whose payloads and outputs are `never`, and no
39
+ * real map is assignable to that; the call site then needs a cast. Annotating
40
+ * the result instead lets `O` be inferred from the return type, which is what
41
+ * gives the call a real `O` to check the argument against.
42
+ *
43
+ * **What that check is worth here is narrow, so it is worth stating exactly.**
44
+ * Each handler is already checked against `MemOp` by
45
+ * {@link memoryOperationMap}'s own annotation, and was before this call was
46
+ * written — a drifted handler is reported there, at the factory, either way.
47
+ * What the runner adds is agreement between the *declared map type* and
48
+ * `MemOp`: give `MemoryOperationMap` a narrower operation set and this line
49
+ * reports the missing handler, where an unchecked call site would leave it to
50
+ * whoever spreads the map next. The wider hazard — a cast stripping the
51
+ * contextual type from an object *literal*, so no handler is checked at all —
52
+ * is `runNodeEffect`'s (`../module.mjs`), which passes a literal; this call
53
+ * passes an already-annotated result.
54
+ * @type {(uuid?: Uuid) => MemoryRun}
55
+ */
56
+ export declare const memoryRun: (uuid?: Uuid) => MemoryRun;
57
+ /**
58
+ * Runs a memory-only effect using a fresh memory store — a store per call, so
59
+ * nothing written by one `run` is visible to the next. Use {@link memoryRun}
60
+ * to keep one.
61
+ * @type {MemoryRun}
62
+ */
63
+ export declare const run: MemoryRun;
@@ -56,8 +56,42 @@ export const memoryOperationMap = (uuid = randomUUID) => {
56
56
  }
57
57
 
58
58
  /**
59
- * Runs a memory-only effect using a fresh memory store.
60
- * @type {<T, E>(effect: Effect<MemOp, T, E>) => Promise<Result<T, E>>}
59
+ * An {@link asyncRun} runner over {@link MemOp}: an effect in, its `Result` out.
60
+ * @typedef {<T, E>(effect: Effect<MemOp, T, E>) => Promise<Result<T, E>>} MemoryRun
61
61
  */
62
- export const run = effect =>
63
- asyncRun(/** @type {ToAsyncOperationMap<MemOp>} */ (memoryOperationMap()))(effect)
62
+
63
+ /**
64
+ * Creates a runner owning a fresh memory store. Every effect passed to the
65
+ * *same* runner shares that store; a new runner starts empty.
66
+ *
67
+ * **The `MemoryRun` annotation is what types the `asyncRun` call.** `asyncRun`
68
+ * takes a `ToAsyncOperationMap<O>`, a mapped type keyed on `O[0]`, and
69
+ * TypeScript cannot infer `O` back out of one — only a homomorphic
70
+ * `{[K in keyof T]: …}` is reversed. Left to argument inference `O` falls back
71
+ * to its `Operation` constraint, whose payloads and outputs are `never`, and no
72
+ * real map is assignable to that; the call site then needs a cast. Annotating
73
+ * the result instead lets `O` be inferred from the return type, which is what
74
+ * gives the call a real `O` to check the argument against.
75
+ *
76
+ * **What that check is worth here is narrow, so it is worth stating exactly.**
77
+ * Each handler is already checked against `MemOp` by
78
+ * {@link memoryOperationMap}'s own annotation, and was before this call was
79
+ * written — a drifted handler is reported there, at the factory, either way.
80
+ * What the runner adds is agreement between the *declared map type* and
81
+ * `MemOp`: give `MemoryOperationMap` a narrower operation set and this line
82
+ * reports the missing handler, where an unchecked call site would leave it to
83
+ * whoever spreads the map next. The wider hazard — a cast stripping the
84
+ * contextual type from an object *literal*, so no handler is checked at all —
85
+ * is `runNodeEffect`'s (`../module.mjs`), which passes a literal; this call
86
+ * passes an already-annotated result.
87
+ * @type {(uuid?: Uuid) => MemoryRun}
88
+ */
89
+ export const memoryRun = (uuid = randomUUID) => asyncRun(memoryOperationMap(uuid))
90
+
91
+ /**
92
+ * Runs a memory-only effect using a fresh memory store — a store per call, so
93
+ * nothing written by one `run` is visible to the next. Use {@link memoryRun}
94
+ * to keep one.
95
+ * @type {MemoryRun}
96
+ */
97
+ export const run = effect => memoryRun()(effect)
@@ -3,10 +3,13 @@
3
3
  *
4
4
  * @module
5
5
  *
6
- * @import { Key, MemOp } from '../../memory/types.ts'
6
+ * @import { Key } from '../../memory/types.ts'
7
+ * @import { Uuid } from './module.mjs'
7
8
  */
8
9
  export declare const proof: {
9
10
  nodeInterpreter: () => Promise<void>;
10
- reusedOperationMapPersists: () => Promise<void>;
11
+ reusedRunnerPersists: () => Promise<void>;
12
+ runnersDoNotShareStore: () => Promise<void>;
13
+ runIsPerCall: () => Promise<void>;
11
14
  missingKeyThrows: () => Promise<void>;
12
15
  };
@@ -3,16 +3,16 @@
3
3
  *
4
4
  * @module
5
5
  *
6
- * @import { Key, MemOp } from '../../memory/types.ts'
6
+ * @import { Key } from '../../memory/types.ts'
7
+ * @import { Uuid } from './module.mjs'
7
8
  */
8
9
 
9
- import { asyncRun } from '../../module.mjs'
10
10
  import { errorSummary } from '../module.f.mjs'
11
11
  import {
12
- asNominal,
12
+ asBase, asNominal,
13
13
  create, read, write,
14
14
  } from '../../memory/module.f.mjs'
15
- import { memoryOperationMap, run } from './module.mjs'
15
+ import { memoryRun, run } from './module.mjs'
16
16
  import { assert, assertEq } from '../../../asserts/module.f.mjs'
17
17
  import { unwrap } from "../../../types/result/module.f.mjs"
18
18
  import { step, unwrapStep } from '../../module.f.mjs'
@@ -28,8 +28,8 @@ export const proof = {
28
28
  assert(r[0] === 'ok', r)
29
29
  assertEq(r[1], 2)
30
30
  },
31
- reusedOperationMapPersists: async () => {
32
- const runner = asyncRun(/** @type {import('../../types.ts').ToAsyncOperationMap<MemOp>} */ (memoryOperationMap()))
31
+ reusedRunnerPersists: async () => {
32
+ const runner = memoryRun()
33
33
  // `unwrapStep` empties the channel, so what the runner hands back is
34
34
  // an `ok` and these unwraps are total.
35
35
  const key = unwrap(await runner(unwrapStep(create(1), errorSummary)))
@@ -37,6 +37,36 @@ export const proof = {
37
37
  const result = unwrap(await runner(unwrapStep(read(key), errorSummary)))
38
38
  assertEq(result, 2)
39
39
  },
40
+ runnersDoNotShareStore: async () => {
41
+ // Both runners mint the *same* key id, so the id cannot be what tells
42
+ // them apart — only store ownership can. A store shared between
43
+ // runners (module-level rather than per call) passes every other proof
44
+ // here; this is the one that fails it.
45
+ /** @type {Uuid} */
46
+ const uuid = () => 'fixed'
47
+ const a = memoryRun(uuid)
48
+ const b = memoryRun(uuid)
49
+ const key = unwrap(await a(unwrapStep(create(1), errorSummary)))
50
+ const result = await b(read(key)).then(
51
+ () => undefined,
52
+ error => error,
53
+ )
54
+ assert(result instanceof Error, result)
55
+ assertEq(result.message, 'memory key not found: fixed', result)
56
+ },
57
+ runIsPerCall: async () => {
58
+ // `run` builds a runner per call, so the store the first call wrote to
59
+ // is gone by the second. One runner shared across every `run` — the
60
+ // other half of the store-ownership mutant — passes every other proof
61
+ // here, including `runnersDoNotShareStore`.
62
+ const key = unwrap(await run(unwrapStep(create(1), errorSummary)))
63
+ const result = await run(read(key)).then(
64
+ () => undefined,
65
+ error => error,
66
+ )
67
+ assert(result instanceof Error, result)
68
+ assertEq(result.message, `memory key not found: ${asBase(key)}`, result)
69
+ },
40
70
  missingKeyThrows: async () => {
41
71
  /** @type {Key<number>} */
42
72
  const key = asNominal('missing')
@@ -16,13 +16,20 @@
16
16
  * @import { IoResult, Server as EffectServer, Headers, Module, NodeOp, RequestListener as Erl, NodeProgram, NodeProgramOptions, WriteConsoles, TestContext, TestFn, } from './types.ts'
17
17
  * @import { Result } from '../../types/result/types.ts'
18
18
  * @import { StringMap } from '../../types/object/types.ts'
19
+ * @import { Nullable } from '../../types/nullable/types.ts'
19
20
  */
20
21
  import type { Effect } from '../types.ts';
21
22
  import type { Headers, NodeOp, NodeProgram } from './types.ts';
22
23
  import type { Result } from '../../types/result/types.ts';
23
24
  import type { StringMap } from '../../types/object/types.ts';
25
+ export type _Socket = {
26
+ readonly end: (data: string) => void;
27
+ };
24
28
  export type _Server = {
25
- readonly listen: (port: number) => void;
29
+ readonly listen: (port: number, host: string) => void;
30
+ readonly once: (event: string, f: (e: unknown) => void) => void;
31
+ on(event: string, f: (req: unknown, socket: _Socket) => void): void;
32
+ readonly removeListener: (event: string, f: (e: unknown) => void) => void;
26
33
  };
27
34
  export type _Readable = AsyncIterable<Uint8Array>;
28
35
  export type _IncomingMessage = _Readable & {
@@ -33,6 +40,7 @@ export type _IncomingMessage = _Readable & {
33
40
  export type _ServerResponse = {
34
41
  readonly writeHead: (status: number, headers: StringMap<string>) => _ServerResponse;
35
42
  readonly end: (body: Uint8Array) => void;
43
+ readonly headersSent: boolean;
36
44
  };
37
45
  export type _RequestListener = (req: _IncomingMessage, res: _ServerResponse) => Promise<void>;
38
46
  export type _EffectToPromise = <T, E>(effect: Effect<NodeOp, T, E>) => Promise<Result<T, E>>;
@@ -29,6 +29,45 @@ import type { All, Access, Await, Console, CreateExclusive, CreateServer, Engine
29
29
  * @type {(info: IoErrorInfo) => IoError}
30
30
  */
31
31
  export declare const ioError: (info: IoErrorInfo) => IoError;
32
+ /**
33
+ * The host a {@link Listen} refuses.
34
+ *
35
+ * Node treats `''` exactly as it treats an omitted argument and binds the
36
+ * unspecified address — measured on Linux with Node 22.22.2, where
37
+ * `listen(0, '')` reports `0.0.0.0`, and on Darwin with Node 23.11.0, where it
38
+ * reports `::`. **Which** unspecified address is the platform's business; that
39
+ * it is one of them is universal. `Listen` takes the host precisely so that
40
+ * an address is stated rather than inherited, and a missing configuration value
41
+ * arriving as `''` inherits the widest one there is. Every runner refuses it, so
42
+ * a program proven against the virtual one binds where the Node one binds.
43
+ *
44
+ * @type {string}
45
+ */
46
+ export declare const emptyHost: string;
47
+ /**
48
+ * Node's own code for an argument it rejects, reported here for a value Node
49
+ * itself accepts: a caller reading `IoError.code` should not have to learn a
50
+ * second vocabulary for a refusal that is the runner's own.
51
+ *
52
+ * @type {string}
53
+ */
54
+ export declare const emptyHostCode: string;
55
+ /** Node's message shape for {@link emptyHostCode} — `The argument '<name>'
56
+ * <reason>. Received <value>`.
57
+ *
58
+ * @type {string}
59
+ */
60
+ export declare const emptyHostMessage: string;
61
+ /**
62
+ * The failure a runner reports for {@link emptyHost}.
63
+ *
64
+ * The virtual runner answers with this value and the Node runner throws an
65
+ * `Error` carrying the same two literals, which is what keeps the two from
66
+ * drifting apart on a refusal neither inherits from Node.
67
+ *
68
+ * @type {IoError}
69
+ */
70
+ export declare const emptyHostError: IoError;
32
71
  /**
33
72
  * Normalizes a **thrown** value into an {@link IoError}: the OS error code when
34
73
  * the host attached a string one, and a message that is the `Error`'s own or
@@ -37,6 +37,52 @@ import {
37
37
  */
38
38
  export const ioError = info => ['ioError', info]
39
39
 
40
+ /**
41
+ * The host a {@link Listen} refuses.
42
+ *
43
+ * Node treats `''` exactly as it treats an omitted argument and binds the
44
+ * unspecified address — measured on Linux with Node 22.22.2, where
45
+ * `listen(0, '')` reports `0.0.0.0`, and on Darwin with Node 23.11.0, where it
46
+ * reports `::`. **Which** unspecified address is the platform's business; that
47
+ * it is one of them is universal. `Listen` takes the host precisely so that
48
+ * an address is stated rather than inherited, and a missing configuration value
49
+ * arriving as `''` inherits the widest one there is. Every runner refuses it, so
50
+ * a program proven against the virtual one binds where the Node one binds.
51
+ *
52
+ * @type {string}
53
+ */
54
+ export const emptyHost = ''
55
+
56
+ /**
57
+ * Node's own code for an argument it rejects, reported here for a value Node
58
+ * itself accepts: a caller reading `IoError.code` should not have to learn a
59
+ * second vocabulary for a refusal that is the runner's own.
60
+ *
61
+ * @type {string}
62
+ */
63
+ export const emptyHostCode = 'ERR_INVALID_ARG_VALUE'
64
+
65
+ /** Node's message shape for {@link emptyHostCode} — `The argument '<name>'
66
+ * <reason>. Received <value>`.
67
+ *
68
+ * @type {string}
69
+ */
70
+ export const emptyHostMessage = `The argument 'host' must not be empty. Received ''`
71
+
72
+ /**
73
+ * The failure a runner reports for {@link emptyHost}.
74
+ *
75
+ * The virtual runner answers with this value and the Node runner throws an
76
+ * `Error` carrying the same two literals, which is what keeps the two from
77
+ * drifting apart on a refusal neither inherits from Node.
78
+ *
79
+ * @type {IoError}
80
+ */
81
+ export const emptyHostError = ioError({
82
+ code: emptyHostCode,
83
+ message: emptyHostMessage,
84
+ })
85
+
40
86
  /**
41
87
  * Normalizes a **thrown** value into an {@link IoError}: the OS error code when
42
88
  * the host attached a string one, and a message that is the `Error`'s own or