functionalscript 0.44.0 → 0.46.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/README.md +5 -3
- package/fjs/asn.1/module.f.mjs +8 -1
- package/fjs/asn.1/proof.f.d.mts +15 -0
- package/fjs/asn.1/proof.f.mjs +31 -3
- package/fjs/asserts/module.f.d.mts +14 -0
- package/fjs/asserts/module.f.mjs +20 -0
- package/fjs/asserts/proof.f.d.mts +3 -0
- package/fjs/asserts/proof.f.mjs +15 -1
- package/fjs/basen/base128/module.f.mjs +22 -5
- package/fjs/basen/base128/proof.f.d.mts +3 -1
- package/fjs/basen/base128/proof.f.mjs +3 -1
- package/fjs/basen/base64/module.f.mjs +7 -3
- package/fjs/basen/base64/proof.f.d.mts +3 -1
- package/fjs/basen/base64/proof.f.mjs +7 -4
- package/fjs/basen/cbase32/proof.f.d.mts +3 -1
- package/fjs/basen/cbase32/proof.f.mjs +3 -1
- package/fjs/bnf/data/module.f.d.mts +32 -6
- package/fjs/bnf/data/module.f.mjs +112 -7
- package/fjs/bnf/data/proof.f.d.mts +2 -0
- package/fjs/bnf/data/proof.f.mjs +74 -4
- package/fjs/bnf/data/types.d.ts +20 -2
- package/fjs/bnf/descent/module.f.d.mts +34 -5
- package/fjs/bnf/descent/module.f.mjs +176 -54
- package/fjs/bnf/descent/proof.f.d.mts +3 -0
- package/fjs/bnf/descent/proof.f.mjs +189 -27
- package/fjs/bnf/descent/types.d.ts +24 -18
- package/fjs/bnf/ll1/module.f.d.mts +74 -6
- package/fjs/bnf/ll1/module.f.mjs +297 -95
- package/fjs/bnf/ll1/proof.f.d.mts +17 -2
- package/fjs/bnf/ll1/proof.f.mjs +372 -137
- package/fjs/bnf/ll1/types.d.ts +25 -27
- package/fjs/bnf/matcher/module.f.d.mts +66 -0
- package/fjs/bnf/matcher/module.f.mjs +81 -0
- package/fjs/bnf/matcher/proof.f.d.mts +10 -0
- package/fjs/bnf/matcher/proof.f.mjs +79 -0
- package/fjs/bnf/matcher/types.d.ts +54 -0
- package/fjs/bnf/module.f.d.mts +15 -6
- package/fjs/bnf/module.f.mjs +52 -11
- package/fjs/bnf/proof.f.d.mts +2 -0
- package/fjs/bnf/proof.f.mjs +79 -3
- package/fjs/bnf/testlib.f.d.mts +31 -0
- package/fjs/bnf/testlib.f.mjs +80 -0
- package/fjs/bnf/token_symbol/module.f.d.mts +4 -3
- package/fjs/bnf/token_symbol/module.f.mjs +7 -6
- package/fjs/bnf/token_symbol/proof.f.mjs +5 -2
- package/fjs/bnf/token_symbol/types.d.ts +2 -2
- package/fjs/bnf/types.d.ts +10 -3
- package/fjs/cas/cli/module.f.d.mts +1 -1
- package/fjs/cas/cli/module.f.mjs +14 -20
- package/fjs/cas/cli/proof.f.d.mts +4 -4
- package/fjs/cas/cli/proof.f.mjs +47 -34
- package/fjs/cas/evo/module.f.d.mts +71 -31
- package/fjs/cas/evo/module.f.mjs +223 -138
- package/fjs/cas/evo/proof.f.d.mts +10 -1
- package/fjs/cas/evo/proof.f.mjs +311 -226
- package/fjs/cas/evo/types.d.ts +45 -9
- package/fjs/cas/module.f.d.mts +18 -32
- package/fjs/cas/module.f.mjs +164 -176
- package/fjs/cas/proof.f.d.mts +11 -8
- package/fjs/cas/proof.f.mjs +259 -147
- package/fjs/cas/types.d.ts +24 -10
- package/fjs/ci/common/module.f.d.mts +1 -1
- package/fjs/ci/common/module.f.mjs +1 -0
- package/fjs/ci/config/module.f.d.mts +3 -3
- package/fjs/ci/config/module.f.mjs +3 -3
- package/fjs/ci/module.f.d.mts +5 -5
- package/fjs/ci/module.f.mjs +8 -7
- package/fjs/ci/nix/module.f.d.mts +7 -5
- package/fjs/ci/nix/module.f.mjs +13 -12
- package/fjs/ci/nix/proof.f.d.mts +2 -0
- package/fjs/ci/nix/proof.f.mjs +4 -4
- package/fjs/ci/proof.f.d.mts +4 -2
- package/fjs/ci/proof.f.mjs +13 -8
- package/fjs/cli/module.f.d.mts +4 -6
- package/fjs/cli/module.f.mjs +4 -8
- package/fjs/cli/proof.f.d.mts +4 -2
- package/fjs/cli/proof.f.mjs +21 -18
- package/fjs/cli/types.d.ts +2 -3
- package/fjs/common/monoid/module.f.d.mts +70 -12
- package/fjs/common/monoid/module.f.mjs +177 -14
- package/fjs/common/monoid/proof.f.d.mts +12 -1
- package/fjs/common/monoid/proof.f.mjs +88 -4
- package/fjs/common/monoid/types.d.ts +23 -0
- package/fjs/crypto/hmac/module.f.mjs +2 -2
- package/fjs/crypto/secp/proof.f.d.mts +3 -1
- package/fjs/crypto/secp/proof.f.mjs +3 -1
- package/fjs/crypto/sha2/module.f.mjs +3 -1
- package/fjs/crypto/sha2/proof.f.d.mts +4 -1
- package/fjs/crypto/sha2/proof.f.mjs +27 -1
- package/fjs/crypto/sha2/types.d.ts +11 -0
- package/fjs/crypto/sign/module.f.mjs +2 -2
- package/fjs/crypto/vdf/module.f.d.mts +23 -4
- package/fjs/crypto/vdf/module.f.mjs +6 -4
- package/fjs/dev/module.f.d.mts +17 -5
- package/fjs/dev/module.f.mjs +60 -30
- package/fjs/dev/update/module.f.d.mts +11 -3
- package/fjs/dev/update/module.f.mjs +16 -11
- package/fjs/dev/update/proof.f.d.mts +4 -3
- package/fjs/dev/update/proof.f.mjs +11 -7
- package/fjs/djs/module.f.d.mts +13 -5
- package/fjs/djs/module.f.mjs +31 -16
- package/fjs/djs/parser/module.f.d.mts +16 -3
- package/fjs/djs/parser/module.f.mjs +135 -16
- package/fjs/djs/parser/proof.f.d.mts +8 -1
- package/fjs/djs/parser/proof.f.mjs +287 -13
- package/fjs/djs/parser/types.d.ts +7 -1
- package/fjs/djs/proof.f.d.mts +20 -1
- package/fjs/djs/proof.f.mjs +190 -12
- package/fjs/djs/serializer/module.f.d.mts +25 -8
- package/fjs/djs/serializer/module.f.mjs +66 -19
- package/fjs/djs/serializer/proof.f.d.mts +5 -0
- package/fjs/djs/serializer/proof.f.mjs +23 -1
- package/fjs/djs/tokenizer/module.f.d.mts +17 -5
- package/fjs/djs/tokenizer/module.f.mjs +120 -73
- package/fjs/djs/tokenizer/proof.f.d.mts +3 -0
- package/fjs/djs/tokenizer/proof.f.mjs +86 -67
- package/fjs/djs/transpiler/module.f.d.mts +13 -19
- package/fjs/djs/transpiler/module.f.mjs +79 -72
- package/fjs/djs/transpiler/types.d.ts +29 -0
- package/fjs/djs/types.d.ts +7 -1
- package/fjs/effects/list/module.f.d.mts +23 -12
- package/fjs/effects/list/module.f.mjs +16 -12
- package/fjs/effects/list/types.d.ts +27 -7
- package/fjs/effects/memory/module.f.d.mts +6 -3
- package/fjs/effects/memory/module.f.mjs +7 -7
- package/fjs/effects/memory/proof.f.d.mts +4 -0
- package/fjs/effects/memory/proof.f.mjs +18 -9
- package/fjs/effects/memory/types.d.ts +4 -3
- package/fjs/effects/mock/module.f.d.mts +28 -4
- package/fjs/effects/mock/module.f.mjs +39 -5
- package/fjs/effects/mock/types.d.ts +10 -1
- package/fjs/effects/module.d.mts +12 -2
- package/fjs/effects/module.f.d.mts +469 -281
- package/fjs/effects/module.f.mjs +538 -299
- package/fjs/effects/module.mjs +11 -2
- package/fjs/effects/node/memory/module.d.mts +7 -2
- package/fjs/effects/node/memory/module.mjs +9 -5
- package/fjs/effects/node/memory/proof.d.mts +2 -0
- package/fjs/effects/node/memory/proof.mjs +12 -5
- package/fjs/effects/node/module.d.mts +8 -2
- package/fjs/effects/node/module.f.d.mts +183 -43
- package/fjs/effects/node/module.f.mjs +260 -62
- package/fjs/effects/node/module.mjs +61 -50
- package/fjs/effects/node/proof.f.d.mts +28 -2
- package/fjs/effects/node/proof.f.mjs +161 -42
- package/fjs/effects/node/types.d.ts +106 -18
- package/fjs/effects/node/virtual/module.f.d.mts +21 -4
- package/fjs/effects/node/virtual/module.f.mjs +113 -70
- package/fjs/effects/node/virtual/proof.f.d.mts +31 -2
- package/fjs/effects/node/virtual/proof.f.mjs +201 -8
- package/fjs/effects/proof.f.d.mts +69 -34
- package/fjs/effects/proof.f.mjs +413 -130
- package/fjs/effects/types.d.ts +161 -33
- package/fjs/emergent_testing/all.test.d.mts +8 -0
- package/fjs/emergent_testing/all.test.mjs +14 -0
- package/fjs/emergent_testing/module.f.d.mts +22 -10
- package/fjs/emergent_testing/module.f.mjs +119 -85
- package/fjs/emergent_testing/proof.f.d.mts +21 -7
- package/fjs/emergent_testing/proof.f.mjs +169 -35
- package/fjs/emergent_testing/types.d.ts +22 -4
- package/fjs/fsc/bnf.f.d.mts +3 -0
- package/fjs/fsc/bnf.f.mjs +4 -1
- package/fjs/fsc/json.f.d.mts +3 -0
- package/fjs/fsc/json.f.mjs +4 -1
- package/fjs/fsc/module.f.d.mts +9 -0
- package/fjs/fsc/module.f.mjs +5 -3
- package/fjs/fsm/module.f.d.mts +14 -4
- package/fjs/fsm/module.f.mjs +54 -37
- package/fjs/fsm/proof.f.d.mts +5 -0
- package/fjs/fsm/proof.f.mjs +87 -115
- package/fjs/js/keywords/module.f.d.mts +52 -0
- package/fjs/js/keywords/module.f.mjs +72 -0
- package/fjs/{emergent_testing/scenarios/return-value.pass.d.ts → js/keywords/proof.f.d.mts} +1 -1
- package/fjs/js/keywords/proof.f.mjs +13 -0
- package/fjs/js/tokenizer/module.f.d.mts +30 -3
- package/fjs/js/tokenizer/module.f.mjs +161 -211
- package/fjs/js/tokenizer/proof.f.d.mts +1 -0
- package/fjs/js/tokenizer/proof.f.mjs +54 -24
- package/fjs/js/tokenizer/types.d.ts +33 -24
- package/fjs/mcp/cas/module.f.d.mts +1 -6
- package/fjs/mcp/cas/module.f.mjs +55 -51
- package/fjs/mcp/cas/proof.f.d.mts +15 -0
- package/fjs/mcp/cas/proof.f.mjs +174 -0
- package/fjs/mcp/evo/module.f.d.mts +19 -10
- package/fjs/mcp/evo/module.f.mjs +48 -27
- package/fjs/mcp/evo/proof.f.d.mts +6 -1
- package/fjs/mcp/evo/proof.f.mjs +115 -31
- package/fjs/mcp/module.f.d.mts +39 -4
- package/fjs/mcp/module.f.mjs +14 -12
- package/fjs/mcp/proof.f.d.mts +13 -1
- package/fjs/mcp/proof.f.mjs +120 -61
- package/fjs/media/html/module.f.d.mts +12 -0
- package/fjs/media/html/module.f.mjs +7 -5
- package/fjs/media/html/proof.f.d.mts +3 -0
- package/fjs/media/html/proof.f.mjs +4 -1
- package/fjs/media/json/extended/module.f.d.mts +82 -0
- package/fjs/media/json/extended/module.f.mjs +153 -0
- package/fjs/media/json/extended/proof.f.d.mts +42 -0
- package/fjs/media/json/extended/proof.f.mjs +127 -0
- package/fjs/media/json/extended/types.d.ts +23 -0
- package/fjs/media/json/module.f.d.mts +8 -2
- package/fjs/media/json/module.f.mjs +43 -41
- package/fjs/media/json/number/module.f.d.mts +59 -0
- package/fjs/media/json/number/module.f.mjs +136 -0
- package/fjs/media/json/number/proof.f.d.mts +24 -0
- package/fjs/media/json/number/proof.f.mjs +86 -0
- package/fjs/media/json/number/types.d.ts +28 -0
- package/fjs/media/json/parser/module.f.d.mts +25 -13
- package/fjs/media/json/parser/module.f.mjs +133 -72
- package/fjs/media/json/parser/proof.f.d.mts +5 -0
- package/fjs/media/json/parser/proof.f.mjs +31 -1
- package/fjs/media/json/parser/types.d.ts +38 -14
- package/fjs/media/json/rtti/module.f.d.mts +1 -1
- package/fjs/media/json/rtti/module.f.mjs +1 -1
- package/fjs/media/json/rtti/proof.f.d.mts +3 -0
- package/fjs/media/json/rtti/proof.f.mjs +12 -12
- package/fjs/media/json/schema/module.f.d.mts +61 -27
- package/fjs/media/json/schema/module.f.mjs +218 -63
- package/fjs/media/json/schema/proof.f.d.mts +41 -1
- package/fjs/media/json/schema/proof.f.mjs +220 -9
- package/fjs/media/json/serializer/module.f.d.mts +44 -0
- package/fjs/media/json/serializer/module.f.mjs +71 -9
- package/fjs/media/json/tokenizer/module.f.d.mts +8 -0
- package/fjs/media/json/tokenizer/module.f.mjs +31 -8
- package/fjs/media/json/tokenizer/proof.f.d.mts +6 -0
- package/fjs/media/json/tokenizer/proof.f.mjs +62 -21
- package/fjs/media/json/types.d.ts +36 -10
- package/fjs/media/lock/module.f.d.mts +100 -0
- package/fjs/media/lock/module.f.mjs +125 -0
- package/fjs/media/lock/proof.f.d.mts +33 -0
- package/fjs/media/lock/proof.f.mjs +196 -0
- package/fjs/media/lock/types.d.ts +15 -0
- package/fjs/media/module.f.d.mts +6 -5
- package/fjs/media/module.f.mjs +8 -7
- package/fjs/media/nix/module.f.d.mts +13 -0
- package/fjs/media/nix/module.f.mjs +4 -2
- package/fjs/media/nix/proof.f.d.mts +3 -0
- package/fjs/media/nix/proof.f.mjs +4 -1
- package/fjs/media/note/module.f.d.mts +121 -0
- package/fjs/media/note/module.f.mjs +131 -0
- package/fjs/media/note/proof.f.d.mts +29 -0
- package/fjs/media/note/proof.f.mjs +150 -0
- package/fjs/media/note/types.d.ts +10 -0
- package/fjs/media/proof.f.d.mts +4 -1
- package/fjs/media/proof.f.mjs +40 -21
- package/fjs/media/revision/module.f.d.mts +83 -7
- package/fjs/media/revision/module.f.mjs +127 -23
- package/fjs/media/revision/proof.f.d.mts +14 -0
- package/fjs/media/revision/proof.f.mjs +93 -2
- package/fjs/media/revision/types.d.ts +34 -5
- package/fjs/media/type/module.f.d.mts +53 -18
- package/fjs/media/type/module.f.mjs +87 -97
- package/fjs/media/type/proof.f.d.mts +17 -0
- package/fjs/media/type/proof.f.mjs +73 -13
- package/fjs/module.d.mts +5 -0
- package/fjs/module.f.d.mts +8 -0
- package/fjs/module.f.mjs +33 -10
- package/fjs/module.mjs +6 -0
- package/fjs/nanvm/proof.f.mjs +3 -3
- package/fjs/nanvm/rust/module.f.mjs +1 -1
- package/fjs/nanvm/update/module.f.d.mts +4 -4
- package/fjs/nanvm/update/module.f.mjs +8 -9
- package/fjs/nanvm/update/proof.f.mjs +4 -3
- package/fjs/path/module.f.d.mts +8 -0
- package/fjs/path/module.f.mjs +4 -2
- package/fjs/proof.f.d.mts +7 -3
- package/fjs/proof.f.mjs +41 -12
- package/fjs/protocol/json_rpc/module.f.d.mts +3 -3
- package/fjs/protocol/json_rpc/module.f.mjs +10 -7
- package/fjs/protocol/json_rpc/proof.f.d.mts +6 -0
- package/fjs/protocol/json_rpc/proof.f.mjs +26 -5
- package/fjs/protocol/mcp/module.f.d.mts +10 -13
- package/fjs/protocol/mcp/module.f.mjs +74 -58
- package/fjs/protocol/mcp/proof.f.d.mts +16 -3
- package/fjs/protocol/mcp/proof.f.mjs +224 -69
- package/fjs/protocol/mcp/stdio/module.f.d.mts +17 -11
- package/fjs/protocol/mcp/stdio/module.f.mjs +39 -33
- package/fjs/protocol/mcp/stdio/proof.f.d.mts +5 -3
- package/fjs/protocol/mcp/stdio/proof.f.mjs +46 -13
- package/fjs/protocol/mcp/stdio/types.d.ts +14 -0
- package/fjs/protocol/mcp/types.d.ts +17 -6
- package/fjs/sul/id/module.f.d.mts +4 -0
- package/fjs/sul/id/module.f.mjs +6 -6
- package/fjs/sul/level/hash/module.f.d.mts +4 -1
- package/fjs/sul/level/hash/module.f.mjs +6 -4
- package/fjs/sul/level/hash/proof.f.d.mts +4 -0
- package/fjs/sul/level/hash/proof.f.mjs +7 -4
- package/fjs/sul/level/literal/module.f.d.mts +4 -1
- package/fjs/sul/level/literal/module.f.mjs +4 -3
- package/fjs/sul/level/literal/proof.f.d.mts +3 -0
- package/fjs/sul/level/literal/proof.f.mjs +4 -1
- package/fjs/sul/module.f.d.mts +5 -3
- package/fjs/sul/module.f.mjs +23 -17
- package/fjs/sul/proof.f.d.mts +4 -0
- package/fjs/sul/proof.f.mjs +5 -2
- package/fjs/text/ascii/module.f.d.mts +26 -0
- package/fjs/text/ascii/module.f.mjs +49 -1
- package/fjs/text/ascii/proof.f.d.mts +10 -0
- package/fjs/text/ascii/proof.f.mjs +33 -1
- package/fjs/text/code_point/module.f.d.mts +29 -3
- package/fjs/text/code_point/module.f.mjs +32 -9
- package/fjs/text/code_point/proof.f.d.mts +2 -0
- package/fjs/text/code_point/proof.f.mjs +39 -0
- package/fjs/text/module.f.d.mts +4 -2
- package/fjs/text/module.f.mjs +4 -3
- package/fjs/text/proof.f.d.mts +3 -0
- package/fjs/text/proof.f.mjs +4 -1
- package/fjs/text/sgr/module.f.d.mts +6 -5
- package/fjs/text/sgr/module.f.mjs +8 -8
- package/fjs/text/sgr/proof.f.d.mts +3 -0
- package/fjs/text/sgr/proof.f.mjs +4 -1
- package/fjs/text/utf16/module.f.d.mts +5 -1
- package/fjs/text/utf16/module.f.mjs +38 -35
- package/fjs/text/utf16/proof.f.d.mts +3 -1
- package/fjs/text/utf16/proof.f.mjs +19 -2
- package/fjs/text/utf8/module.f.d.mts +9 -5
- package/fjs/text/utf8/module.f.mjs +20 -20
- package/fjs/types/array/module.f.d.mts +2 -1
- package/fjs/types/array/module.f.mjs +16 -4
- package/fjs/types/bigfloat/module.f.d.mts +21 -1
- package/fjs/types/bigfloat/module.f.mjs +33 -7
- package/fjs/types/bigfloat/proof.f.d.mts +1 -0
- package/fjs/types/bigfloat/proof.f.mjs +46 -0
- package/fjs/types/bigint/module.f.d.mts +4 -0
- package/fjs/types/bigint/module.f.mjs +4 -3
- package/fjs/types/bit_vec/module.f.d.mts +10 -16
- package/fjs/types/bit_vec/module.f.mjs +99 -95
- package/fjs/types/bit_vec/proof.f.d.mts +6 -0
- package/fjs/types/bit_vec/proof.f.mjs +31 -5
- package/fjs/types/btree/find/module.f.d.mts +5 -1
- package/fjs/types/btree/find/module.f.mjs +5 -5
- package/fjs/types/btree/find/proof.f.d.mts +5 -1
- package/fjs/types/btree/find/proof.f.mjs +5 -3
- package/fjs/types/btree/module.f.d.mts +3 -0
- package/fjs/types/btree/module.f.mjs +3 -2
- package/fjs/types/btree/proof.f.d.mts +5 -1
- package/fjs/types/btree/proof.f.mjs +5 -3
- package/fjs/types/btree/remove/module.f.d.mts +11 -0
- package/fjs/types/btree/remove/module.f.mjs +10 -10
- package/fjs/types/btree/remove/proof.f.d.mts +3 -0
- package/fjs/types/btree/remove/proof.f.mjs +4 -1
- package/fjs/types/btree/set/module.f.d.mts +9 -0
- package/fjs/types/btree/set/module.f.mjs +14 -17
- package/fjs/types/btree/set/proof.f.d.mts +3 -0
- package/fjs/types/btree/set/proof.f.mjs +16 -1
- package/fjs/types/btree/types/module.f.d.mts +2 -1
- package/fjs/types/btree/types/module.f.mjs +2 -1
- package/fjs/types/byte_set/module.f.d.mts +20 -4
- package/fjs/types/byte_set/module.f.mjs +18 -8
- package/fjs/types/byte_set/proof.f.d.mts +3 -1
- package/fjs/types/byte_set/proof.f.mjs +10 -8
- package/fjs/types/function/compare/module.f.d.mts +3 -2
- package/fjs/types/function/compare/module.f.mjs +13 -5
- package/fjs/types/function/module.f.d.mts +8 -1
- package/fjs/types/function/module.f.mjs +8 -1
- package/fjs/types/function/operator/module.f.d.mts +2 -1
- package/fjs/types/function/operator/module.f.mjs +2 -2
- package/fjs/types/list/module.f.d.mts +10 -3
- package/fjs/types/list/module.f.mjs +6 -4
- package/fjs/types/list/proof.f.d.mts +4 -1
- package/fjs/types/list/proof.f.mjs +4 -2
- package/fjs/types/nibble_set/module.f.d.mts +2 -1
- package/fjs/types/nibble_set/module.f.mjs +2 -2
- package/fjs/types/nominal/module.f.d.mts +2 -1
- package/fjs/types/nominal/module.f.mjs +2 -1
- package/fjs/types/nullable/module.f.d.mts +26 -6
- package/fjs/types/nullable/module.f.mjs +25 -6
- package/fjs/types/nullable/proof.f.d.mts +4 -0
- package/fjs/types/nullable/proof.f.mjs +15 -0
- package/fjs/types/number/module.f.d.mts +4 -0
- package/fjs/types/number/module.f.mjs +4 -3
- package/fjs/types/object/module.f.d.mts +26 -4
- package/fjs/types/object/module.f.mjs +26 -7
- package/fjs/types/object/proof.f.d.mts +5 -2
- package/fjs/types/object/proof.f.mjs +6 -3
- package/fjs/types/object/structurally_same/module.f.d.mts +39 -0
- package/fjs/types/object/structurally_same/module.f.mjs +59 -0
- package/fjs/types/object/structurally_same/proof.f.d.mts +6 -0
- package/fjs/types/object/structurally_same/proof.f.mjs +73 -0
- package/fjs/types/ordered_map/module.f.d.mts +5 -0
- package/fjs/types/ordered_map/module.f.mjs +5 -4
- package/fjs/types/ordered_map/proof.f.d.mts +3 -0
- package/fjs/types/ordered_map/proof.f.mjs +4 -1
- package/fjs/types/patricia_trie/module.f.d.mts +2 -1
- package/fjs/types/patricia_trie/module.f.mjs +27 -12
- package/fjs/types/patricia_trie/proof.f.d.mts +3 -0
- package/fjs/types/patricia_trie/proof.f.mjs +4 -1
- package/fjs/types/prime_field/module.f.d.mts +3 -1
- package/fjs/types/prime_field/module.f.mjs +3 -2
- package/fjs/types/range/module.f.d.mts +2 -1
- package/fjs/types/range/module.f.mjs +2 -2
- package/fjs/types/range_map/module.f.d.mts +6 -0
- package/fjs/types/range_map/module.f.mjs +6 -9
- package/fjs/types/range_map/proof.f.d.mts +5 -1
- package/fjs/types/range_map/proof.f.mjs +5 -3
- package/fjs/types/range_set/module.f.d.mts +5 -0
- package/fjs/types/range_set/module.f.mjs +1 -0
- package/fjs/types/range_set/proof.f.d.mts +3 -0
- package/fjs/types/range_set/proof.f.mjs +4 -1
- package/fjs/types/result/module.d.mts +8 -0
- package/fjs/types/result/module.f.d.mts +37 -7
- package/fjs/types/result/module.f.mjs +38 -8
- package/fjs/types/result/module.mjs +9 -1
- package/fjs/types/result/proof.f.d.mts +5 -0
- package/fjs/types/result/proof.f.mjs +22 -2
- package/fjs/types/rtti/common/module.f.d.mts +44 -14
- package/fjs/types/rtti/common/module.f.mjs +42 -36
- package/fjs/types/rtti/common/proof.f.d.mts +4 -0
- package/fjs/types/rtti/common/proof.f.mjs +10 -7
- package/fjs/types/rtti/data/module.f.d.mts +134 -0
- package/fjs/types/rtti/data/module.f.mjs +1053 -0
- package/fjs/types/rtti/data/proof.f.d.mts +76 -0
- package/fjs/types/rtti/data/proof.f.mjs +589 -0
- package/fjs/types/rtti/data/types.d.ts +83 -0
- package/fjs/types/rtti/module.f.d.mts +12 -5
- package/fjs/types/rtti/module.f.mjs +7 -5
- package/fjs/types/rtti/parse/module.f.d.mts +48 -0
- package/fjs/types/rtti/parse/module.f.mjs +45 -34
- package/fjs/types/rtti/parse/proof.f.d.mts +3 -2
- package/fjs/types/rtti/parse/proof.f.mjs +51 -52
- package/fjs/types/rtti/proof.f.d.mts +3 -1
- package/fjs/types/rtti/proof.f.mjs +6 -2
- package/fjs/types/rtti/ts/module.f.d.mts +68 -9
- package/fjs/types/rtti/ts/module.f.mjs +258 -30
- package/fjs/types/rtti/ts/proof.f.d.mts +44 -0
- package/fjs/types/rtti/ts/proof.f.mjs +152 -4
- package/fjs/types/rtti/ts/types.d.ts +25 -1
- package/fjs/types/rtti/types.d.ts +40 -0
- package/fjs/types/sorted_list/module.f.d.mts +4 -1
- package/fjs/types/sorted_list/module.f.mjs +21 -12
- package/fjs/types/sorted_list/proof.f.d.mts +3 -1
- package/fjs/types/sorted_list/proof.f.mjs +3 -1
- package/fjs/types/sorted_set/module.f.d.mts +49 -1
- package/fjs/types/sorted_set/module.f.mjs +26 -2
- package/fjs/types/sorted_set/proof.f.d.mts +4 -1
- package/fjs/types/sorted_set/proof.f.mjs +19 -2
- package/fjs/types/string/module.f.d.mts +4 -0
- package/fjs/types/string/module.f.mjs +4 -3
- package/fjs/types/string_set/module.f.d.mts +3 -1
- package/fjs/types/string_set/module.f.mjs +3 -2
- package/fjs/types/ts/module.f.d.mts +2 -0
- package/fjs/types/ts/module.f.mjs +3 -3
- package/fjs/types/ts/proof.f.d.mts +1 -0
- package/fjs/types/ts/proof.f.mjs +5 -0
- package/fjs/types/ts/types.d.ts +6 -1
- package/fjs/types/uint8array/module.f.d.mts +13 -2
- package/fjs/types/uint8array/module.f.mjs +20 -15
- package/fjs/website/module.f.d.mts +5 -2
- package/fjs/website/module.f.mjs +6 -8
- package/fjs/website/proof.f.mjs +2 -1
- package/package.json +3 -3
- package/fjs/asn.1/types.js +0 -6
- package/fjs/asserts/types.js +0 -6
- package/fjs/basen/types.js +0 -6
- package/fjs/bnf/data/types.js +0 -6
- package/fjs/bnf/descent/types.js +0 -6
- package/fjs/bnf/ll1/types.js +0 -6
- package/fjs/bnf/token_symbol/types.js +0 -6
- package/fjs/bnf/types.js +0 -6
- package/fjs/cas/evo/types.js +0 -7
- package/fjs/cas/types.js +0 -6
- package/fjs/ci/common/types.js +0 -1
- package/fjs/ci/nix/types.js +0 -6
- package/fjs/ci/types.js +0 -6
- package/fjs/cli/types.js +0 -6
- package/fjs/common/monoid/types.js +0 -6
- package/fjs/crypto/pow/types.js +0 -6
- package/fjs/crypto/secp/types.js +0 -6
- package/fjs/crypto/sha2/types.js +0 -6
- package/fjs/crypto/sign/types.js +0 -6
- package/fjs/crypto/vdf/types.js +0 -6
- package/fjs/dev/package_json/module.f.d.mts +0 -32
- package/fjs/dev/package_json/module.f.mjs +0 -37
- package/fjs/dev/package_json/proof.f.d.mts +0 -6
- package/fjs/dev/package_json/proof.f.mjs +0 -32
- package/fjs/dev/types.js +0 -6
- package/fjs/djs/ast/types.js +0 -8
- package/fjs/djs/parser/types.js +0 -7
- package/fjs/djs/tokenizer/types.js +0 -7
- package/fjs/djs/types.js +0 -7
- package/fjs/effects/eff/module.f.d.mts +0 -10
- package/fjs/effects/eff/module.f.mjs +0 -68
- package/fjs/effects/eff/proof.f.d.mts +0 -12
- package/fjs/effects/eff/proof.f.mjs +0 -66
- package/fjs/effects/eff/types.d.ts +0 -71
- package/fjs/effects/eff/types.js +0 -6
- package/fjs/effects/list/types.js +0 -6
- package/fjs/effects/memory/types.js +0 -6
- package/fjs/effects/mock/types.js +0 -6
- package/fjs/effects/node/types.js +0 -6
- package/fjs/effects/node/virtual/types.js +0 -7
- package/fjs/effects/types.js +0 -6
- package/fjs/emergent_testing/all.test.d.ts +0 -1
- package/fjs/emergent_testing/all.test.js +0 -5
- package/fjs/emergent_testing/scenarios/all.d.ts +0 -1
- package/fjs/emergent_testing/scenarios/all.js +0 -1
- package/fjs/emergent_testing/scenarios/async-subtests.fail.d.ts +0 -6
- package/fjs/emergent_testing/scenarios/async-subtests.fail.js +0 -9
- package/fjs/emergent_testing/scenarios/async-subtests.pass.d.ts +0 -6
- package/fjs/emergent_testing/scenarios/async-subtests.pass.js +0 -9
- package/fjs/emergent_testing/scenarios/async.fail.d.ts +0 -3
- package/fjs/emergent_testing/scenarios/async.fail.js +0 -6
- package/fjs/emergent_testing/scenarios/async.pass.d.ts +0 -3
- package/fjs/emergent_testing/scenarios/async.pass.js +0 -5
- package/fjs/emergent_testing/scenarios/fail.fail.d.ts +0 -3
- package/fjs/emergent_testing/scenarios/fail.fail.js +0 -3
- package/fjs/emergent_testing/scenarios/return-value.pass.js +0 -4
- package/fjs/emergent_testing/scenarios/thenable.pass.d.ts +0 -5
- package/fjs/emergent_testing/scenarios/thenable.pass.js +0 -11
- package/fjs/emergent_testing/scenarios/thenable2.pass.d.ts +0 -5
- package/fjs/emergent_testing/scenarios/thenable2.pass.js +0 -3
- package/fjs/emergent_testing/scenarios/throw.pass.d.ts +0 -5
- package/fjs/emergent_testing/scenarios/throw.pass.js +0 -3
- package/fjs/emergent_testing/types.js +0 -6
- package/fjs/js/tokenizer/types.js +0 -6
- package/fjs/media/html/types.js +0 -6
- package/fjs/media/json/parser/types.js +0 -6
- package/fjs/media/json/tokenizer/types.js +0 -6
- package/fjs/media/json/types.js +0 -13
- package/fjs/media/nix/types.js +0 -6
- package/fjs/media/revision/types.js +0 -8
- package/fjs/media/type/types.js +0 -6
- package/fjs/media/types.js +0 -7
- package/fjs/nanvm/types.js +0 -11
- package/fjs/protocol/json_rpc/types.js +0 -8
- package/fjs/protocol/mcp/types.js +0 -8
- package/fjs/sul/id/types.js +0 -6
- package/fjs/sul/level/hash/types.js +0 -6
- package/fjs/sul/level/literal/types.js +0 -6
- package/fjs/sul/types.js +0 -6
- package/fjs/text/sgr/types.js +0 -6
- package/fjs/text/types.js +0 -6
- package/fjs/text/utf16/types.js +0 -6
- package/fjs/text/utf8/types.js +0 -6
- package/fjs/types/array/types.js +0 -6
- package/fjs/types/bigfloat/types.js +0 -6
- package/fjs/types/bigint/types.js +0 -6
- package/fjs/types/bit_vec/types.js +0 -6
- package/fjs/types/btree/find/types.js +0 -6
- package/fjs/types/btree/types/types.js +0 -6
- package/fjs/types/byte_set/types.js +0 -6
- package/fjs/types/function/compare/types.js +0 -6
- package/fjs/types/function/operator/types.js +0 -6
- package/fjs/types/function/types.js +0 -6
- package/fjs/types/list/types.js +0 -6
- package/fjs/types/nibble_set/types.js +0 -6
- package/fjs/types/nominal/types.js +0 -6
- package/fjs/types/nullable/types.js +0 -6
- package/fjs/types/object/types.js +0 -8
- package/fjs/types/option/types.js +0 -6
- package/fjs/types/ordered_map/types.js +0 -6
- package/fjs/types/patricia_trie/types.js +0 -6
- package/fjs/types/phantom/types.js +0 -11
- package/fjs/types/prime_field/types.js +0 -6
- package/fjs/types/range/types.js +0 -6
- package/fjs/types/range_map/types.js +0 -6
- package/fjs/types/result/types.js +0 -6
- package/fjs/types/rtti/common/types.js +0 -1
- package/fjs/types/rtti/parse/types.js +0 -1
- package/fjs/types/rtti/ts/types.js +0 -1
- package/fjs/types/rtti/types.js +0 -1
- package/fjs/types/rtti/validate/module.f.d.mts +0 -6
- package/fjs/types/rtti/validate/module.f.mjs +0 -169
- package/fjs/types/rtti/validate/proof.f.d.mts +0 -125
- package/fjs/types/rtti/validate/proof.f.mjs +0 -437
- package/fjs/types/rtti/validate/types.d.ts +0 -6
- package/fjs/types/rtti/validate/types.js +0 -1
- package/fjs/types/sorted_list/types.js +0 -6
- package/fjs/types/sorted_set/types.js +0 -6
- package/fjs/types/string_set/types.js +0 -6
- package/fjs/types/ts/types.js +0 -8
|
@@ -9,10 +9,70 @@ import type { MemOp } from '../memory/types.ts';
|
|
|
9
9
|
import type { Nominal } from '../../types/nominal/types.ts';
|
|
10
10
|
import type { Result } from '../../types/result/types.ts';
|
|
11
11
|
import type { StringMap } from '../../types/object/types.ts';
|
|
12
|
-
import type { Effect, Operation, ToAsyncOperationMap } from '../types.ts';
|
|
12
|
+
import type { Effect, NotImplemented, Operation, ToAsyncOperationMap } from '../types.ts';
|
|
13
13
|
import type { List } from '../list/types.ts';
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* A host failure, normalized: whatever the runtime threw reduced to a
|
|
16
|
+
* serializable record. `code` is the OS error code when the host supplied one
|
|
17
|
+
* (`'ENOENT'`, `'EEXIST'`), absent otherwise.
|
|
18
|
+
*
|
|
19
|
+
* It is a tagged tuple for the same reason {@link NotImplemented} is — the two
|
|
20
|
+
* share an error channel, and the tag is what tells them apart. That
|
|
21
|
+
* distinction is the whole reason this type exists: with a bare `unknown`
|
|
22
|
+
* error, `NotImplemented | unknown` collapses to `unknown` and a program can no
|
|
23
|
+
* longer tell "this runner cannot do it" from "the host tried and failed".
|
|
24
|
+
*
|
|
25
|
+
* Normalizing also keeps the channel serializable. A thrown `Error` carries a
|
|
26
|
+
* stack, a `cause`, and arbitrary own properties; none of it survives a wire
|
|
27
|
+
* hop, and a runner in another process could not reproduce it.
|
|
28
|
+
*/
|
|
29
|
+
export type IoError = readonly ['ioError', IoErrorInfo];
|
|
30
|
+
export type IoErrorInfo = {
|
|
31
|
+
readonly code?: string;
|
|
32
|
+
readonly message: string;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* The result of an operation with no failures of its own: it either produces
|
|
36
|
+
* its value or reports that the runner does not implement it.
|
|
37
|
+
*
|
|
38
|
+
* Every operation's return type is a `Result`, including the ones that cannot
|
|
39
|
+
* fail on their own terms — an operation left on a raw contract would be a hole
|
|
40
|
+
* in the error channel, and a runner may omit a handler for any of them.
|
|
41
|
+
*/
|
|
42
|
+
export type OpResult<T> = Result<T, NotImplemented>;
|
|
43
|
+
/**
|
|
44
|
+
* The error channel of anything that performs host IO: a normalized host
|
|
45
|
+
* failure, or the report that the runner does not implement the operation.
|
|
46
|
+
*
|
|
47
|
+
* It is one name rather than a union spelled at each site, and that is a
|
|
48
|
+
* migration property rather than brevity. An effect that does no IO *yet* is
|
|
49
|
+
* one added `readFile` away from doing some, and if each signature names its
|
|
50
|
+
* own errors, that one change walks up every enclosing signature — the failure
|
|
51
|
+
* mode that sank `throws` clauses elsewhere, where engineers eventually
|
|
52
|
+
* declared everything throwing rather than maintain the cascade. Declaring the
|
|
53
|
+
* standard channel once is that concession made deliberately: an IO-touching
|
|
54
|
+
* effect says it fails *the way node IO fails*, and gaining a new way to do so
|
|
55
|
+
* changes nothing above it.
|
|
56
|
+
*
|
|
57
|
+
* It is not a licence to widen. An operation with failures of its own extends
|
|
58
|
+
* the channel (`IoChannel | ParseError`), and a computation whose errors are
|
|
59
|
+
* genuinely narrower should say so — this is the default for IO, not a ceiling.
|
|
60
|
+
*/
|
|
61
|
+
export type IoChannel = NotImplemented | IoError;
|
|
62
|
+
/**
|
|
63
|
+
* The result of an operation that performs host IO: its value, a normalized
|
|
64
|
+
* host failure, or the missing-handler report.
|
|
65
|
+
*/
|
|
66
|
+
export type IoResult<T> = Result<T, IoChannel>;
|
|
67
|
+
/**
|
|
68
|
+
* Runs its effects concurrently and answers each one's whole `Result`.
|
|
69
|
+
*
|
|
70
|
+
* The nesting is deliberate and belongs to the runner: this envelope says
|
|
71
|
+
* whether `all` itself could be dispatched, and each inner `Result` is what
|
|
72
|
+
* that effect answered. `allOk` (`./module.f.mjs`) is the collapse a fallible
|
|
73
|
+
* chain wants.
|
|
74
|
+
*/
|
|
75
|
+
export type All = ['all', <T, E>(...effects: Effect<never, T, E>[]) => OpResult<readonly Result<T, E>[]>];
|
|
16
76
|
export type Fetch = ['fetch', (url: string) => IoResult<Vec>];
|
|
17
77
|
export type MakeDirectoryOptions = {
|
|
18
78
|
readonly recursive: true;
|
|
@@ -42,7 +102,7 @@ export type WriteFile = readonly ['writeFile', (path: string, data: Vec) => IoRe
|
|
|
42
102
|
export type Rm = readonly ['rm', (path: string) => IoResult<void>];
|
|
43
103
|
export type Rename = readonly ['rename', (src: string, dst: string) => IoResult<void>];
|
|
44
104
|
export type ReadBytes = readonly ['readBytes', (path: string, offset: number, size: number) => IoResult<Vec>];
|
|
45
|
-
export type RandomInt = readonly ['randomInt', () => number];
|
|
105
|
+
export type RandomInt = readonly ['randomInt', () => OpResult<number>];
|
|
46
106
|
export type ExecResult = {
|
|
47
107
|
readonly stdout: string;
|
|
48
108
|
readonly stderr: string;
|
|
@@ -66,7 +126,7 @@ export type CreateExclusive = readonly ['createExclusive', (path: string) => IoR
|
|
|
66
126
|
*/
|
|
67
127
|
export type WriteBytes = readonly ['writeBytes', (path: string, offset: number, data: Vec) => IoResult<void>];
|
|
68
128
|
/** @internal */
|
|
69
|
-
export type _WriteLoop = <O extends Operation>(offset: number, e: List<O,
|
|
129
|
+
export type _WriteLoop = <O extends Operation>(offset: number, e: List<O, Vec, IoChannel>) => Effect<O | WriteBytes, void, IoChannel>;
|
|
70
130
|
/** File metadata returned by `stat`. Only `size` (in bytes) for now. */
|
|
71
131
|
export type FileStat = {
|
|
72
132
|
readonly size: number;
|
|
@@ -86,11 +146,16 @@ export type ServerResponse = {
|
|
|
86
146
|
readonly headers: Headers;
|
|
87
147
|
readonly body: Vec;
|
|
88
148
|
};
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
149
|
+
/**
|
|
150
|
+
* An HTTP request handler. The channel is `never` because the response frame
|
|
151
|
+
* *is* where a failure goes — a listener that cannot answer still has a status
|
|
152
|
+
* code to answer with, so absorbing is the contract rather than an omission.
|
|
153
|
+
*/
|
|
154
|
+
export type RequestListener<O extends Operation> = (_: IncomingMessage) => Effect<O, ServerResponse, never>;
|
|
155
|
+
export type CreateServer = ['createServer', (listener: RequestListener<Operation>) => OpResult<Server>];
|
|
156
|
+
export type Listen = ['listen', (server: Server, port: number) => OpResult<void>];
|
|
92
157
|
export type Http = CreateServer | Listen;
|
|
93
|
-
export type Forever = ['forever', () => never];
|
|
158
|
+
export type Forever = ['forever', () => OpResult<never>];
|
|
94
159
|
export type Module = StringMap<unknown>;
|
|
95
160
|
export type Import = ['import', (path: string) => IoResult<Module>];
|
|
96
161
|
/** Named output streams accepted by the `Write` effect. */
|
|
@@ -100,7 +165,7 @@ export type WriteConsoles = 'stdout' | 'stderr';
|
|
|
100
165
|
* a `Vec`. The Node runner maps each stream name to the appropriate fd and
|
|
101
166
|
* delegates to the OS via `stream.write()` with backpressure handling.
|
|
102
167
|
*/
|
|
103
|
-
export type Write = readonly ['write', (stream: WriteConsoles, data: Vec) => void];
|
|
168
|
+
export type Write = readonly ['write', (stream: WriteConsoles, data: Vec) => OpResult<void>];
|
|
104
169
|
export type Console = (s: string) => Effect<Write, void>;
|
|
105
170
|
/** Named input streams accepted by the `Read` effect. */
|
|
106
171
|
export type ReadConsoles = 'stdin';
|
|
@@ -112,10 +177,10 @@ export type ReadConsoles = 'stdin';
|
|
|
112
177
|
* rather than the interpreter. Back-pressure is naturally sequential — the next
|
|
113
178
|
* `read` is only issued once the previous byte is consumed.
|
|
114
179
|
*/
|
|
115
|
-
export type Read = readonly ['read', (stream: ReadConsoles) => number | null];
|
|
180
|
+
export type Read = readonly ['read', (stream: ReadConsoles) => OpResult<number | null>];
|
|
116
181
|
/** @internal */
|
|
117
182
|
export type _UtfList = EffectList<number>;
|
|
118
|
-
export type Now = readonly ['now', () => number];
|
|
183
|
+
export type Now = readonly ['now', () => OpResult<number>];
|
|
119
184
|
/**
|
|
120
185
|
* The outcome of a `Sandbox` operation.
|
|
121
186
|
*
|
|
@@ -132,7 +197,7 @@ export type SandboxResult<T> = {
|
|
|
132
197
|
*/
|
|
133
198
|
readonly duration: number;
|
|
134
199
|
};
|
|
135
|
-
export type Sandbox = readonly ['sandbox', <T>(f: () => T) => SandboxResult<T
|
|
200
|
+
export type Sandbox = readonly ['sandbox', <T>(f: () => T) => OpResult<SandboxResult<T>>];
|
|
136
201
|
/**
|
|
137
202
|
* Resolves the return value of a test function inside the effect runner.
|
|
138
203
|
* If `p` is a real `Promise`, it is awaited and rejections propagate as
|
|
@@ -140,7 +205,7 @@ export type Sandbox = readonly ['sandbox', <T>(f: () => T) => SandboxResult<T>];
|
|
|
140
205
|
* (objects with a `.then` method that are not `instanceof Promise`) are
|
|
141
206
|
* treated as ordinary values — not awaited. See `fjs/dev/tf/README.md`.
|
|
142
207
|
*/
|
|
143
|
-
export type Await = readonly ['await', (p: unknown) => readonly [unknown]];
|
|
208
|
+
export type Await = readonly ['await', (p: unknown) => OpResult<readonly [unknown]>];
|
|
144
209
|
/**
|
|
145
210
|
* Signature of a framework test-registration function (e.g. `nodeTest.test`,
|
|
146
211
|
* `bunTest.test`). Returns `Promise<void>` so async sub-tests can be awaited.
|
|
@@ -157,10 +222,18 @@ export type TestFn = (name: string, options: {
|
|
|
157
222
|
export type TestContext = {
|
|
158
223
|
readonly test: TestFn;
|
|
159
224
|
};
|
|
160
|
-
/**
|
|
161
|
-
|
|
225
|
+
/**
|
|
226
|
+
* Operation that registers a named test with the active `TestContext`.
|
|
227
|
+
*
|
|
228
|
+
* The callback's `never` is the honest reading of what an external framework
|
|
229
|
+
* accepts. Node `--test`, Bun and Deno take a body that either returns or
|
|
230
|
+
* throws; there is no channel to answer a failure through, so the body absorbs
|
|
231
|
+
* its own — which `emergent_testing` does, by panicking, since a throw is the
|
|
232
|
+
* one failure signal those frameworks understand.
|
|
233
|
+
*/
|
|
234
|
+
export type Test = readonly ['test', (ctx: TestContext, name: string, expectFailure: boolean, test: (t: TestContext) => Effect<Test | All | Await, void, never>) => OpResult<void>];
|
|
162
235
|
export type NodeOp = Access | All | Await | Fetch | Fs | Http | Forever | Import | MemOp | Now | RandomInt | Read | Sandbox | Write | Test;
|
|
163
|
-
export type NodeEffect<T> = Effect<NodeOp, T>;
|
|
236
|
+
export type NodeEffect<T, E = IoChannel> = Effect<NodeOp, T, E>;
|
|
164
237
|
export type NodeOperationMap = ToAsyncOperationMap<NodeOp>;
|
|
165
238
|
/**
|
|
166
239
|
* The environment variables.
|
|
@@ -199,5 +272,20 @@ export type NodeProgramOptions = {
|
|
|
199
272
|
readonly nodeVersion?: string;
|
|
200
273
|
readonly inlineTestContext: boolean;
|
|
201
274
|
};
|
|
202
|
-
|
|
275
|
+
/**
|
|
276
|
+
* A program: run it, and it answers an exit code.
|
|
277
|
+
*
|
|
278
|
+
* The code lives in a `Result` rather than in a bare `number`, and the two
|
|
279
|
+
* branches say which kind of code it is — `ok(0)` for success, `error(n)` for
|
|
280
|
+
* failure. A bare `number` could not: nothing could short-circuit on it, so a
|
|
281
|
+
* chain that ran one program and then another had to re-test the code by hand,
|
|
282
|
+
* and `step(…, () => pure(0))` was a way to report a failed program as a clean
|
|
283
|
+
* exit that the type system had no opinion about.
|
|
284
|
+
*
|
|
285
|
+
* **`T` is the literal `0`**, so a success carries no information beyond
|
|
286
|
+
* having succeeded, and `r[1]` is the exit code in *either* branch. A runner
|
|
287
|
+
* reads the code without asking which branch it came from; a caller that cares
|
|
288
|
+
* whether the program failed asks `r[0]`.
|
|
289
|
+
*/
|
|
290
|
+
export type Program<O extends Operation> = (options: NodeProgramOptions) => Effect<O, 0, number>;
|
|
203
291
|
export type NodeProgram = Program<NodeOp>;
|
|
@@ -2,16 +2,33 @@
|
|
|
2
2
|
* Virtual Node-effect operations for filesystem and process tests.
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
|
+
*
|
|
6
|
+
* @import { Vec } from '../../../types/bit_vec/types.ts'
|
|
7
|
+
* @import { PartialMemOperationMap, RunInstance } from '../../mock/types.ts'
|
|
8
|
+
* @import { Dirent, FileStat, IoError, IoResult, Module, NodeOp, NodeProgramOptions, SandboxResult } from '../types.ts'
|
|
9
|
+
* @import { Result } from '../../../types/result/types.ts'
|
|
10
|
+
* @import { Error } from '../../../types/result/types.ts'
|
|
11
|
+
* @import { Dir, State, _Entity } from './types.ts'
|
|
5
12
|
*/
|
|
6
13
|
import type { RunInstance } from '../../mock/types.ts';
|
|
7
14
|
import type { NodeOp, NodeProgramOptions } from '../types.ts';
|
|
8
15
|
import type { State } from './types.ts';
|
|
9
|
-
/** @import { Key } from '../../memory/types.ts' */
|
|
10
|
-
/** @import { Dirent, FileStat, IoResult, Module, NodeOp, NodeProgramOptions, SandboxResult } from '../types.ts' */
|
|
11
|
-
/** @import { Dir, State, _Entity } from './types.ts' */
|
|
12
16
|
/** @type {State} */
|
|
13
17
|
export declare const emptyState: State;
|
|
14
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* The virtual runner.
|
|
20
|
+
*
|
|
21
|
+
* **It implements part of `NodeOp`, and says so.** `exec`, `createServer`,
|
|
22
|
+
* `listen`, `forever` and `test` have no meaning against an in-memory
|
|
23
|
+
* filesystem, and they used to be present as `todo` handlers — entries that
|
|
24
|
+
* existed only to satisfy a total operation map and threw when reached. They
|
|
25
|
+
* are simply absent now, so a program that asks for one gets
|
|
26
|
+
* `error(notImplemented)` back through its own continuation and decides what an
|
|
27
|
+
* incompatible runner means for it, which is what `NotImplemented` was
|
|
28
|
+
* introduced for. A command that is not a `NodeOp` at all still panics.
|
|
29
|
+
*
|
|
30
|
+
* @type {RunInstance<NodeOp, State>}
|
|
31
|
+
*/
|
|
15
32
|
export declare const virtual: RunInstance<NodeOp, State>;
|
|
16
33
|
/**
|
|
17
34
|
* Safe, inert defaults for every {@link NodeProgramOptions} field, intended for
|
|
@@ -2,20 +2,23 @@
|
|
|
2
2
|
* Virtual Node-effect operations for filesystem and process tests.
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
|
+
*
|
|
6
|
+
* @import { Vec } from '../../../types/bit_vec/types.ts'
|
|
7
|
+
* @import { PartialMemOperationMap, RunInstance } from '../../mock/types.ts'
|
|
8
|
+
* @import { Dirent, FileStat, IoError, IoResult, Module, NodeOp, NodeProgramOptions, SandboxResult } from '../types.ts'
|
|
9
|
+
* @import { Result } from '../../../types/result/types.ts'
|
|
10
|
+
* @import { Error } from '../../../types/result/types.ts'
|
|
11
|
+
* @import { Dir, State, _Entity } from './types.ts'
|
|
5
12
|
*/
|
|
6
13
|
|
|
7
|
-
import { todo } from '../../../asserts/module.f.mjs'
|
|
14
|
+
import { assert, todo } from '../../../asserts/module.f.mjs'
|
|
8
15
|
import { isProperPrefix, join, parse } from '../../../path/module.f.mjs'
|
|
9
16
|
import { utf8ToString } from '../../../text/module.f.mjs'
|
|
10
|
-
/** @import { Vec } from '../../../types/bit_vec/types.ts' */
|
|
11
17
|
import { empty, length, maxLengthBytes, msb, vec } from '../../../types/bit_vec/module.f.mjs'
|
|
12
18
|
import { error, ok } from '../../../types/result/module.f.mjs'
|
|
13
|
-
import {
|
|
14
|
-
|
|
19
|
+
import { ioError, nodeCommands } from '../module.f.mjs'
|
|
20
|
+
import { partialRun } from '../../mock/module.f.mjs'
|
|
15
21
|
import { asBase, asNominal } from '../../memory/module.f.mjs'
|
|
16
|
-
/** @import { Key } from '../../memory/types.ts' */
|
|
17
|
-
/** @import { Dirent, FileStat, IoResult, Module, NodeOp, NodeProgramOptions, SandboxResult } from '../types.ts' */
|
|
18
|
-
/** @import { Dir, State, _Entity } from './types.ts' */
|
|
19
22
|
|
|
20
23
|
/** @type {State} */
|
|
21
24
|
export const emptyState = {
|
|
@@ -43,10 +46,13 @@ const operation = op => {
|
|
|
43
46
|
}
|
|
44
47
|
const [first, ...rest] = path
|
|
45
48
|
const subDir = dir[first]
|
|
46
|
-
|
|
49
|
+
// `instanceof Array`, not `Array.isArray`: the latter narrows to `any[]`,
|
|
50
|
+
// which `readonly Vec[]` is not assignable to, so its negative branch never
|
|
51
|
+
// removes a `readonly` array from `_Entity`. Only `instanceof` narrows here.
|
|
52
|
+
if (typeof subDir !== 'object' || subDir instanceof Array) {
|
|
47
53
|
return op(dir, path)
|
|
48
54
|
}
|
|
49
|
-
const [newSubDir, r] = f(
|
|
55
|
+
const [newSubDir, r] = f(subDir, rest)
|
|
50
56
|
return [{ ...dir, [first]: newSubDir }, r]
|
|
51
57
|
}
|
|
52
58
|
return path => state => {
|
|
@@ -64,12 +70,22 @@ const readOperation = op => operation((dir, path) => [dir, op(dir, path)])
|
|
|
64
70
|
|
|
65
71
|
const okVoid = ok(undefined)
|
|
66
72
|
|
|
73
|
+
/**
|
|
74
|
+
* A virtual host failure. The virtual runner reports the same normalized
|
|
75
|
+
* {@link IoError} the Node runner does, so a program cannot tell the two apart
|
|
76
|
+
* by the shape of what it catches — which is what makes a proof against the
|
|
77
|
+
* virtual filesystem evidence about the real one.
|
|
78
|
+
*
|
|
79
|
+
* @type {(message: string) => Error<IoError>}
|
|
80
|
+
*/
|
|
81
|
+
const fail = message => error(ioError({ message }))
|
|
82
|
+
|
|
67
83
|
/** @type {(recursive: boolean) => (dir: Dir, path: readonly string[]) => readonly [Dir, IoResult<void>]} */
|
|
68
84
|
const mkdirOp = recursive => (dir, path) => {
|
|
69
85
|
let d = {}
|
|
70
86
|
let i = path.length
|
|
71
87
|
if (i > 1 && !recursive) {
|
|
72
|
-
return [dir,
|
|
88
|
+
return [dir, fail('non-recursive')]
|
|
73
89
|
}
|
|
74
90
|
while (i > 0) {
|
|
75
91
|
i -= 1
|
|
@@ -83,7 +99,7 @@ const mkdirOp = recursive => (dir, path) => {
|
|
|
83
99
|
const mkdir = recursive => operation(mkdirOp(recursive))
|
|
84
100
|
|
|
85
101
|
/** Absent-path error mirroring Node's `ENOENT`, so `isNotFound` recognizes it. */
|
|
86
|
-
const enoent = error({ code: 'ENOENT' })
|
|
102
|
+
const enoent = error(ioError({ code: 'ENOENT', message: 'no such file or directory' }))
|
|
87
103
|
|
|
88
104
|
/** @type {(path: string) => (state: State) => readonly [State, IoResult<Vec>]} */
|
|
89
105
|
const readFile = readOperation((dir, path) => {
|
|
@@ -91,15 +107,18 @@ const readFile = readOperation((dir, path) => {
|
|
|
91
107
|
const file = dir[path[0]]
|
|
92
108
|
if (typeof file === 'function') { throw new Error(`'${path[0]}' is a JsModule; readFile not supported`) }
|
|
93
109
|
if (file === undefined) { return enoent }
|
|
94
|
-
|
|
95
|
-
|
|
110
|
+
// `operation`'s wrapper descends into every plain-object (`Dir`) entry
|
|
111
|
+
// before this op ever runs, and the `JsModule` case already threw above,
|
|
112
|
+
// so `file` here is always a `Vec[]` — never a bare `Dir`.
|
|
113
|
+
assert(Array.isArray(file), `'${path[0]}' is not a file`)
|
|
114
|
+
const chunks = file
|
|
96
115
|
const capBits = maxLengthBytes * 8n
|
|
97
116
|
let result = empty
|
|
98
117
|
for (const chunk of chunks) {
|
|
99
118
|
const chunkLen = length(chunk)
|
|
100
119
|
if (chunkLen === 0n) { continue }
|
|
101
120
|
if (length(result) + chunkLen > capBits) {
|
|
102
|
-
return
|
|
121
|
+
return fail(`File size exceeds maximum allowed size of ${maxLengthBytes} bytes`)
|
|
103
122
|
}
|
|
104
123
|
result = msb.concat(result)(chunk)
|
|
105
124
|
}
|
|
@@ -108,13 +127,13 @@ const readFile = readOperation((dir, path) => {
|
|
|
108
127
|
|
|
109
128
|
/** @type {(path: string) => (state: State) => readonly [State, IoResult<Module>]} */
|
|
110
129
|
const import_ = readOperation((dir, path) => {
|
|
111
|
-
if (path.length !== 1) { return
|
|
130
|
+
if (path.length !== 1) { return fail('no such file') }
|
|
112
131
|
const entry = dir[path[0]]
|
|
113
|
-
if (typeof entry !== 'function') { return
|
|
132
|
+
if (typeof entry !== 'function') { return fail(`'${path[0]}' is not a JsModule`) }
|
|
114
133
|
return ok(entry())
|
|
115
134
|
})
|
|
116
135
|
|
|
117
|
-
const writeFileError =
|
|
136
|
+
const writeFileError = fail('invalid file')
|
|
118
137
|
|
|
119
138
|
/** @type {(payload: Vec) => (dir: Dir, path: readonly string[]) => readonly [Dir, IoResult<void>]} */
|
|
120
139
|
const writeFileOp = payload => (dir, path) => {
|
|
@@ -129,7 +148,7 @@ const writeFileOp = payload => (dir, path) => {
|
|
|
129
148
|
/** @type {(payload: Vec) => (path: string) => (state: State) => readonly [State, IoResult<void>]} */
|
|
130
149
|
const writeFile = payload => operation(writeFileOp(payload))
|
|
131
150
|
|
|
132
|
-
const invalidPath =
|
|
151
|
+
const invalidPath = fail('invalid path')
|
|
133
152
|
|
|
134
153
|
const { entries } = Object
|
|
135
154
|
|
|
@@ -142,10 +161,10 @@ const readdir = (base, recursive) => readOperation((dir, path) => {
|
|
|
142
161
|
let result = []
|
|
143
162
|
for (const [name, content] of entries(d)) {
|
|
144
163
|
if (content === undefined) { continue }
|
|
145
|
-
const isFile =
|
|
164
|
+
const isFile = content instanceof Array || typeof content !== 'object'
|
|
146
165
|
result = [...result, { name, parentPath, isFile }]
|
|
147
166
|
if (!isFile && recursive) {
|
|
148
|
-
result = [...result, ...f(join(parentPath, name),
|
|
167
|
+
result = [...result, ...f(join(parentPath, name), content)]
|
|
149
168
|
}
|
|
150
169
|
}
|
|
151
170
|
return result
|
|
@@ -162,11 +181,15 @@ const access = readOperation((dir, path) => {
|
|
|
162
181
|
|
|
163
182
|
/** @type {(dir: Dir, path: readonly string[]) => readonly [Dir, IoResult<void>]} */
|
|
164
183
|
const rmOp = (dir, path) => {
|
|
165
|
-
if (path.length !== 1) { return [dir,
|
|
184
|
+
if (path.length !== 1) { return [dir, fail('invalid path')] }
|
|
166
185
|
const [name] = path
|
|
167
186
|
const entry = dir[name]
|
|
168
|
-
if (entry === undefined) { return [dir,
|
|
169
|
-
|
|
187
|
+
if (entry === undefined) { return [dir, fail('no such file')] }
|
|
188
|
+
// No "is a directory" guard here: `operation`'s wrapper descends into
|
|
189
|
+
// every plain-object (`Dir`) entry before this op ever runs, so `entry`
|
|
190
|
+
// is always a `Vec[]` or a `JsModule` — never a bare `Dir` — and rm can
|
|
191
|
+
// always proceed. (`rm` on a genuinely non-empty directory instead hits
|
|
192
|
+
// `path.length !== 1` above, once the wrapper has descended into it.)
|
|
170
193
|
const { [name]: _, ...rest } = dir
|
|
171
194
|
return [rest, okVoid]
|
|
172
195
|
}
|
|
@@ -176,7 +199,7 @@ const rm = operation(rmOp)
|
|
|
176
199
|
|
|
177
200
|
/** @type {(dir: Dir, path: readonly string[]) => readonly [Dir, IoResult<_Entity>]} */
|
|
178
201
|
const extractEntity = (dir, path) => {
|
|
179
|
-
if (path.length === 0) { return [dir,
|
|
202
|
+
if (path.length === 0) { return [dir, fail('cannot extract root')] }
|
|
180
203
|
if (path.length === 1) {
|
|
181
204
|
const [name] = path
|
|
182
205
|
const entry = dir[name]
|
|
@@ -186,15 +209,21 @@ const extractEntity = (dir, path) => {
|
|
|
186
209
|
}
|
|
187
210
|
const [first, ...rest] = path
|
|
188
211
|
const sub = dir[first]
|
|
189
|
-
if (sub === undefined ||
|
|
190
|
-
const [newSub, result] = extractEntity(
|
|
212
|
+
if (sub === undefined || sub instanceof Array || typeof sub === 'function') { return [dir, enoent] }
|
|
213
|
+
const [newSub, result] = extractEntity(sub, rest)
|
|
191
214
|
if (result[0] === 'error') { return [dir, result] }
|
|
192
215
|
return [{ ...dir, [first]: newSub }, result]
|
|
193
216
|
}
|
|
194
217
|
|
|
195
218
|
/** @type {(dir: Dir, path: readonly string[], entity: _Entity) => readonly [Dir, IoResult<void>]} */
|
|
196
219
|
const insertEntityAt = (dir, path, entity) => {
|
|
197
|
-
|
|
220
|
+
// `insertEntityAt`'s only external caller, `rename`, always rejects an
|
|
221
|
+
// empty `dst` earlier — `isProperPrefix([], srcParsed)` is true whenever
|
|
222
|
+
// `srcParsed` is non-empty, so renaming onto root is already caught as
|
|
223
|
+
// "onto an ancestor" before this function runs. The recursive self-calls
|
|
224
|
+
// below never pass an empty path either (they only recurse when
|
|
225
|
+
// `path.length > 1`, with a non-empty remainder).
|
|
226
|
+
assert(path.length > 0, 'cannot insert at root')
|
|
198
227
|
if (path.length === 1) {
|
|
199
228
|
const [name] = path
|
|
200
229
|
const existing = dir[name]
|
|
@@ -202,16 +231,16 @@ const insertEntityAt = (dir, path, entity) => {
|
|
|
202
231
|
const entityIsDir = !Array.isArray(entity) && typeof entity === 'object'
|
|
203
232
|
const existingIsDir = !Array.isArray(existing) && typeof existing === 'object'
|
|
204
233
|
if (entityIsDir && !existingIsDir) {
|
|
205
|
-
return [dir,
|
|
234
|
+
return [dir, fail(`cannot overwrite file '${name}' with a directory`)]
|
|
206
235
|
}
|
|
207
236
|
if (!entityIsDir && existingIsDir) {
|
|
208
|
-
return [dir,
|
|
237
|
+
return [dir, fail(`'${name}' is a directory`)]
|
|
209
238
|
}
|
|
210
239
|
if (entityIsDir && existingIsDir) {
|
|
211
|
-
const existingDir =
|
|
240
|
+
const existingDir = existing
|
|
212
241
|
const hasContent = Object.values(existingDir).some(v => v !== undefined)
|
|
213
242
|
if (hasContent) {
|
|
214
|
-
return [dir,
|
|
243
|
+
return [dir, fail(`cannot overwrite non-empty directory '${name}'`)]
|
|
215
244
|
}
|
|
216
245
|
}
|
|
217
246
|
}
|
|
@@ -220,8 +249,8 @@ const insertEntityAt = (dir, path, entity) => {
|
|
|
220
249
|
const [first, ...rest] = path
|
|
221
250
|
const sub = dir[first]
|
|
222
251
|
if (sub === undefined) { return [dir, enoent] }
|
|
223
|
-
if (
|
|
224
|
-
const [newSub, result] = insertEntityAt(
|
|
252
|
+
if (sub instanceof Array || typeof sub === 'function') { return [dir, fail('not a directory')] }
|
|
253
|
+
const [newSub, result] = insertEntityAt(sub, rest, entity)
|
|
225
254
|
if (result[0] === 'error') { return [dir, result] }
|
|
226
255
|
return [{ ...dir, [first]: newSub }, result]
|
|
227
256
|
}
|
|
@@ -236,7 +265,7 @@ const rename = (src, dst) => state => {
|
|
|
236
265
|
// now that source exists, reject if dst is strictly inside src's subtree (rename into own descendant)
|
|
237
266
|
// or if src is strictly inside dst's subtree (rename onto own ancestor)
|
|
238
267
|
if (isProperPrefix(srcParsed, dstParsed) || isProperPrefix(dstParsed, srcParsed)) {
|
|
239
|
-
return [state,
|
|
268
|
+
return [state, fail('cannot rename a directory into its own subtree or onto an ancestor')]
|
|
240
269
|
}
|
|
241
270
|
const [dstRoot, dstResult] = insertEntityAt(srcRoot, dstParsed, srcResult[1])
|
|
242
271
|
if (dstResult[0] === 'error') { return [state, dstResult] }
|
|
@@ -249,13 +278,16 @@ const readBytesOp = (path, offset, size) => readOperation((dir, p) => {
|
|
|
249
278
|
const file = dir[p[0]]
|
|
250
279
|
if (typeof file === 'function') { throw new Error(`'${p[0]}' is a JsModule; readBytes not supported`) }
|
|
251
280
|
if (file === undefined) { return enoent }
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
if (
|
|
257
|
-
if (
|
|
258
|
-
|
|
281
|
+
// `operation`'s wrapper descends into every plain-object (`Dir`) entry
|
|
282
|
+
// before this op ever runs, and the `JsModule` case already threw above,
|
|
283
|
+
// so `file` here is always a `Vec[]` — never a bare `Dir`.
|
|
284
|
+
assert(Array.isArray(file), `'${p[0]}' is not a file`)
|
|
285
|
+
if (!Number.isInteger(offset)) { return fail(`Offset ${offset} is not an integer`) }
|
|
286
|
+
if (!Number.isInteger(size)) { return fail(`Chunk size ${size} is not an integer`) }
|
|
287
|
+
if (offset < 0) { return fail(`Offset ${offset} is negative`) }
|
|
288
|
+
if (size < 0) { return fail(`Chunk size ${size} is negative`) }
|
|
289
|
+
if (BigInt(size) > maxLengthBytes) { return fail(`Chunk size ${size} exceeds maximum allowed size of ${maxLengthBytes} bytes`) }
|
|
290
|
+
const chunks = file
|
|
259
291
|
let toSkip = BigInt(offset) * 8n
|
|
260
292
|
let toRead = BigInt(size) * 8n
|
|
261
293
|
let result = empty
|
|
@@ -282,7 +314,7 @@ const fileSizeBytes = chunks =>
|
|
|
282
314
|
chunks.reduce((acc, c) => acc + Number(length(c) / 8n), 0)
|
|
283
315
|
|
|
284
316
|
/** Absent-path error for an already-existing exclusive create, mirroring `EEXIST`. */
|
|
285
|
-
const eexist = error({ code: 'EEXIST' })
|
|
317
|
+
const eexist = error(ioError({ code: 'EEXIST', message: 'file already exists' }))
|
|
286
318
|
|
|
287
319
|
/** @type {(dir: Dir, path: readonly string[]) => readonly [Dir, IoResult<void>]} */
|
|
288
320
|
const createExclusiveOp = (dir, path) => {
|
|
@@ -307,11 +339,11 @@ const writeBytesRawOp = (offset, data) => (dir, p) => {
|
|
|
307
339
|
const [name] = p
|
|
308
340
|
const file = dir[name]
|
|
309
341
|
if (file === undefined) { return [dir, enoent] } // writeBytes never creates
|
|
310
|
-
if (!Array.isArray(file)) { return [dir,
|
|
311
|
-
if (!Number.isInteger(offset) || offset < 0) { return [dir,
|
|
312
|
-
const chunks =
|
|
342
|
+
if (!Array.isArray(file)) { return [dir, fail(`'${name}' is not a file`)] }
|
|
343
|
+
if (!Number.isInteger(offset) || offset < 0) { return [dir, fail(`Offset ${offset} is invalid`)] }
|
|
344
|
+
const chunks = file
|
|
313
345
|
if (offset !== fileSizeBytes(chunks)) {
|
|
314
|
-
return [dir,
|
|
346
|
+
return [dir, fail(`writeBytes offset ${offset} must equal the file size (append-only)`)]
|
|
315
347
|
}
|
|
316
348
|
return [{ ...dir, [name]: [...chunks, data] }, okVoid]
|
|
317
349
|
}
|
|
@@ -324,43 +356,46 @@ const statOp = readOperation((dir, path) => {
|
|
|
324
356
|
if (path.length !== 1) { return enoent }
|
|
325
357
|
const file = dir[path[0]]
|
|
326
358
|
if (file === undefined) { return enoent }
|
|
327
|
-
if (!Array.isArray(file)) { return
|
|
328
|
-
return ok({ size: fileSizeBytes(
|
|
359
|
+
if (!Array.isArray(file)) { return fail(`'${path[0]}' is not a file`) }
|
|
360
|
+
return ok({ size: fileSizeBytes(file) })
|
|
329
361
|
})
|
|
330
362
|
|
|
331
|
-
/** @type {
|
|
363
|
+
/** @type {PartialMemOperationMap<NodeOp, State>} */
|
|
332
364
|
const map = {
|
|
333
365
|
all: (...a) => state => {
|
|
334
|
-
|
|
366
|
+
// Each entry is the effect's whole `Result`: `all`'s own envelope says
|
|
367
|
+
// only whether the runner could dispatch it, so the inner answers pass
|
|
368
|
+
// through untouched for `allOk` to collapse.
|
|
369
|
+
/** @type {readonly Result<unknown, unknown>[]} */
|
|
335
370
|
let e = []
|
|
336
371
|
for (const i of a) {
|
|
337
372
|
const [ns, ei] = virtual(state)(i)
|
|
338
373
|
state = ns
|
|
339
374
|
e = [...e, ei]
|
|
340
375
|
}
|
|
341
|
-
return [state, e]
|
|
376
|
+
return [state, ok(e)]
|
|
342
377
|
},
|
|
343
378
|
memCreate: value => state => {
|
|
344
379
|
const id = `mem${state.memoryNext}`
|
|
345
|
-
const key =
|
|
380
|
+
const key = asNominal(id)
|
|
346
381
|
return [{
|
|
347
382
|
...state,
|
|
348
383
|
memoryNext: state.memoryNext + 1,
|
|
349
384
|
memoryValues: { ...state.memoryValues, [id]: value },
|
|
350
|
-
}, key]
|
|
385
|
+
}, ok(key)]
|
|
351
386
|
},
|
|
352
387
|
memRead: key => state =>
|
|
353
|
-
[state, state.memoryValues[asBase(key)]],
|
|
388
|
+
[state, ok(state.memoryValues[asBase(key)])],
|
|
354
389
|
memWrite: (key, value) => state => {
|
|
355
390
|
const id = asBase(key)
|
|
356
391
|
return [{
|
|
357
392
|
...state,
|
|
358
393
|
memoryValues: { ...state.memoryValues, [id]: value },
|
|
359
|
-
},
|
|
394
|
+
}, okVoid]
|
|
360
395
|
},
|
|
361
396
|
fetch: url => state => {
|
|
362
397
|
const result = state.internet[url]
|
|
363
|
-
return result === undefined ? [state,
|
|
398
|
+
return result === undefined ? [state, fail('not found')] : [state, ok(result)]
|
|
364
399
|
},
|
|
365
400
|
mkdir: (path, p) => mkdir(p !== undefined)(path),
|
|
366
401
|
readFile,
|
|
@@ -374,12 +409,8 @@ const map = {
|
|
|
374
409
|
createExclusive,
|
|
375
410
|
writeBytes: writeBytesOp,
|
|
376
411
|
stat: statOp,
|
|
377
|
-
randomInt: () => state => [{ ...state, randomNext: state.randomNext + 1 }, state.randomNext],
|
|
378
|
-
|
|
379
|
-
createServer: todo,
|
|
380
|
-
listen: todo,
|
|
381
|
-
forever: todo,
|
|
382
|
-
now: () => state => [state, state.epochNs],
|
|
412
|
+
randomInt: () => state => [{ ...state, randomNext: state.randomNext + 1 }, ok(state.randomNext)],
|
|
413
|
+
now: () => state => [state, ok(state.epochNs)],
|
|
383
414
|
// Virtual sandbox is a pass-through: the fixture's test function is
|
|
384
415
|
// expected to return a `SandboxResult` directly (encoding pass/fail and a
|
|
385
416
|
// chosen duration), so the handler invokes it without try/catch or clock
|
|
@@ -387,23 +418,35 @@ const map = {
|
|
|
387
418
|
// result instead of the runner measuring real execution. A genuine
|
|
388
419
|
// exception in a fixture propagates loudly as a bug in the fixture.
|
|
389
420
|
// See: issues/156-tf-virtual-tests.md
|
|
390
|
-
sandbox: f => state => [state, /** @type {SandboxResult<unknown>} */ (f())],
|
|
391
|
-
await: p => state => [state, [p]],
|
|
392
|
-
test: todo,
|
|
421
|
+
sandbox: f => state => [state, ok(/** @type {SandboxResult<unknown>} */ (f()))],
|
|
422
|
+
await: p => state => [state, ok([p])],
|
|
393
423
|
write: (stream, data) => state => {
|
|
394
424
|
const s = utf8ToString(data)
|
|
395
|
-
return [{ ...state, [stream]: `${state[stream]}${s}` },
|
|
425
|
+
return [{ ...state, [stream]: `${state[stream]}${s}` }, okVoid]
|
|
396
426
|
},
|
|
397
427
|
read: () => state => {
|
|
398
428
|
const [first, ...rest] = state.stdin
|
|
399
429
|
return state.stdin.length === 0
|
|
400
|
-
? [state, null]
|
|
401
|
-
: [{ ...state, stdin: rest }, first]
|
|
430
|
+
? [state, ok(null)]
|
|
431
|
+
: [{ ...state, stdin: rest }, ok(first)]
|
|
402
432
|
},
|
|
403
433
|
}
|
|
404
434
|
|
|
405
|
-
/**
|
|
406
|
-
|
|
435
|
+
/**
|
|
436
|
+
* The virtual runner.
|
|
437
|
+
*
|
|
438
|
+
* **It implements part of `NodeOp`, and says so.** `exec`, `createServer`,
|
|
439
|
+
* `listen`, `forever` and `test` have no meaning against an in-memory
|
|
440
|
+
* filesystem, and they used to be present as `todo` handlers — entries that
|
|
441
|
+
* existed only to satisfy a total operation map and threw when reached. They
|
|
442
|
+
* are simply absent now, so a program that asks for one gets
|
|
443
|
+
* `error(notImplemented)` back through its own continuation and decides what an
|
|
444
|
+
* incompatible runner means for it, which is what `NotImplemented` was
|
|
445
|
+
* introduced for. A command that is not a `NodeOp` at all still panics.
|
|
446
|
+
*
|
|
447
|
+
* @type {RunInstance<NodeOp, State>}
|
|
448
|
+
*/
|
|
449
|
+
export const virtual = partialRun(nodeCommands)(map)
|
|
407
450
|
|
|
408
451
|
const testContext = { test: todo }
|
|
409
452
|
|