functionalscript 0.19.0 → 0.21.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/fs/asn.1/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/asn.1/{test.f.js → proof.f.js} +1 -1
- package/fs/asserts/module.f.d.ts +4 -0
- package/fs/asserts/module.f.js +6 -0
- package/fs/base128/proof.f.d.ts +1 -0
- package/fs/base128/{test.f.js → proof.f.js} +1 -1
- package/fs/bnf/data/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/bnf/data/{test.f.js → proof.f.js} +1 -1
- package/fs/bnf/proof.f.d.ts +3 -0
- package/fs/bnf/{test.f.js → proof.f.js} +1 -1
- package/fs/cas/module.f.js +9 -23
- package/fs/cas/proof.f.d.ts +4 -0
- package/fs/cas/proof.f.js +37 -0
- package/fs/cbase32/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/cbase32/{test.f.js → proof.f.js} +1 -1
- package/fs/ci/bun/module.f.js +2 -7
- package/fs/ci/common/module.f.d.ts +2 -1
- package/fs/ci/common/module.f.js +7 -9
- package/fs/ci/config/module.f.d.ts +12 -3
- package/fs/ci/config/module.f.js +24 -4
- package/fs/ci/deno/module.f.js +2 -5
- package/fs/ci/node/module.f.js +14 -9
- package/fs/ci/playwright/module.f.js +5 -8
- package/fs/ci/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/ci/{test.f.js → proof.f.js} +2 -2
- package/fs/ci/rust/module.f.js +3 -9
- package/fs/crypto/hmac/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/crypto/hmac/{test.f.js → proof.f.js} +1 -1
- package/fs/crypto/secp/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/crypto/secp/{test.f.js → proof.f.js} +1 -1
- package/fs/crypto/sha2/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/crypto/sha2/{test.f.js → proof.f.js} +1 -1
- package/fs/crypto/sign/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/crypto/sign/{test.f.js → proof.f.js} +1 -1
- package/fs/dev/module.f.d.ts +28 -5
- package/fs/dev/module.f.js +38 -28
- package/fs/dev/{test.f.d.ts → proof.f.d.ts} +5 -2
- package/fs/dev/{test.f.js → proof.f.js} +26 -2
- package/fs/dev/version/proof.f.d.ts +3 -0
- package/fs/dev/version/{test.f.js → proof.f.js} +1 -1
- package/fs/djs/ast/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/djs/ast/{test.f.js → proof.f.js} +1 -1
- package/fs/djs/parser/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/djs/parser/{test.f.js → proof.f.js} +1 -1
- package/fs/djs/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/djs/{test.f.js → proof.f.js} +1 -1
- package/fs/djs/serializer/module.f.d.ts +2 -2
- package/fs/djs/serializer/module.f.js +47 -79
- package/fs/djs/serializer/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/djs/serializer/{test.f.js → proof.f.js} +8 -8
- package/fs/djs/tokenizer/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/djs/tokenizer/{test.f.js → proof.f.js} +1 -1
- package/fs/djs/tokenizer-new/module.f.js +1 -1
- package/fs/djs/tokenizer-new/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/djs/tokenizer-new/{test.f.js → proof.f.js} +1 -1
- package/fs/djs/transpiler/module.f.d.ts +15 -0
- package/fs/djs/transpiler/module.f.js +10 -2
- package/fs/djs/transpiler/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/djs/transpiler/{test.f.js → proof.f.js} +1 -1
- package/fs/{dev/tf → emergent-testing}/module.f.d.ts +66 -8
- package/fs/{dev/tf → emergent-testing}/module.f.js +101 -34
- package/fs/{dev/tf → emergent-testing}/module.js +2 -2
- package/fs/{dev/tf/test.f.d.ts → emergent-testing/proof.f.d.ts} +28 -0
- package/fs/{dev/tf/test.f.js → emergent-testing/proof.f.js} +119 -40
- package/fs/emergent-testing/scenarios/async-subtests.fail.d.ts +6 -0
- package/fs/emergent-testing/scenarios/async-subtests.fail.js +9 -0
- package/fs/emergent-testing/scenarios/async-subtests.pass.d.ts +6 -0
- package/fs/emergent-testing/scenarios/async-subtests.pass.js +9 -0
- package/fs/emergent-testing/scenarios/async.fail.d.ts +3 -0
- package/fs/emergent-testing/scenarios/async.fail.js +6 -0
- package/fs/emergent-testing/scenarios/async.pass.d.ts +3 -0
- package/fs/emergent-testing/scenarios/async.pass.js +5 -0
- package/fs/emergent-testing/scenarios/fail.fail.d.ts +3 -0
- package/fs/emergent-testing/scenarios/fail.fail.js +3 -0
- package/fs/emergent-testing/scenarios/return-value.pass.d.ts +3 -0
- package/fs/emergent-testing/scenarios/return-value.pass.js +4 -0
- package/fs/emergent-testing/scenarios/thenable.pass.d.ts +5 -0
- package/fs/emergent-testing/scenarios/thenable.pass.js +11 -0
- package/fs/emergent-testing/scenarios/thenable2.pass.d.ts +5 -0
- package/fs/emergent-testing/scenarios/thenable2.pass.js +3 -0
- package/fs/emergent-testing/scenarios/throw.pass.d.ts +5 -0
- package/fs/{dev/tf/scenarios/throw.pass.f.js → emergent-testing/scenarios/throw.pass.js} +1 -1
- package/fs/fjs/module.f.js +4 -5
- package/fs/fsc/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/fsc/{test.f.js → proof.f.js} +1 -1
- package/fs/fsm/proof.f.d.ts +4 -0
- package/fs/fsm/{test.f.js → proof.f.js} +1 -1
- package/fs/html/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/html/{test.f.js → proof.f.js} +1 -1
- package/fs/io/module.d.ts +1 -1
- package/fs/io/module.f.d.ts +3 -2
- package/fs/io/module.f.js +4 -3
- package/fs/io/module.js +19 -11
- package/fs/js/tokenizer/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/js/tokenizer/{test.f.js → proof.f.js} +1 -1
- package/fs/json/parser/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/json/parser/{test.f.js → proof.f.js} +1 -1
- package/fs/json/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/json/{test.f.js → proof.f.js} +1 -1
- package/fs/json/serializer/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/json/serializer/{test.f.js → proof.f.js} +1 -1
- package/fs/json/tokenizer/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/json/tokenizer/{test.f.js → proof.f.js} +1 -1
- package/fs/path/proof.f.d.ts +5 -0
- package/fs/path/{test.f.js → proof.f.js} +4 -3
- package/fs/sul/id/module.f.js +1 -1
- package/fs/sul/id/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/sul/id/{test.f.js → proof.f.js} +2 -2
- package/fs/sul/level/hash/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/sul/level/hash/{test.f.js → proof.f.js} +2 -2
- package/fs/sul/level/literal/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/sul/level/literal/{test.f.js → proof.f.js} +1 -1
- package/fs/sul/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/sul/{test.f.js → proof.f.js} +2 -2
- package/fs/text/ascii/proof.f.d.ts +3 -0
- package/fs/text/ascii/{test.f.js → proof.f.js} +1 -1
- package/fs/text/code_point/module.f.d.ts +28 -0
- package/fs/text/code_point/module.f.js +31 -0
- package/fs/text/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/text/{test.f.js → proof.f.js} +1 -1
- package/fs/text/sgr/proof.f.d.ts +1 -0
- package/fs/text/sgr/{test.f.js → proof.f.js} +1 -1
- package/fs/text/utf16/module.f.js +3 -53
- package/fs/text/utf16/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/text/utf16/{test.f.js → proof.f.js} +1 -1
- package/fs/text/utf8/module.f.js +3 -25
- package/fs/text/utf8/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/text/utf8/{test.f.js → proof.f.js} +1 -1
- package/fs/types/array/module.f.js +2 -5
- package/fs/types/array/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/array/{test.f.js → proof.f.js} +1 -1
- package/fs/types/bigfloat/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/bigfloat/{test.f.js → proof.f.js} +1 -1
- package/fs/types/bigint/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/bigint/{test.f.js → proof.f.js} +1 -1
- package/fs/types/bit_vec/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/bit_vec/{test.f.js → proof.f.js} +1 -1
- package/fs/types/btree/find/proof.f.d.ts +1 -0
- package/fs/types/btree/find/{test.f.js → proof.f.js} +1 -1
- package/fs/types/btree/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/btree/{test.f.js → proof.f.js} +1 -1
- package/fs/types/btree/remove/proof.f.d.ts +4 -0
- package/fs/types/btree/remove/{test.f.js → proof.f.js} +1 -1
- package/fs/types/btree/set/proof.f.d.ts +1 -0
- package/fs/types/btree/set/{test.f.js → proof.f.js} +1 -1
- package/fs/types/btree/types/module.f.d.ts +8 -0
- package/fs/types/btree/types/module.f.js +8 -0
- package/fs/types/byte_set/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/byte_set/{test.f.js → proof.f.js} +1 -1
- package/fs/types/effects/module.f.d.ts +17 -0
- package/fs/types/effects/module.f.js +17 -0
- package/fs/types/effects/node/module.f.d.ts +60 -5
- package/fs/types/effects/node/module.f.js +12 -1
- package/fs/types/effects/node/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/effects/node/{test.f.js → proof.f.js} +1 -1
- package/fs/types/effects/node/virtual/module.f.js +2 -1
- package/fs/types/effects/proof.f.d.ts +11 -0
- package/fs/types/effects/proof.f.js +57 -0
- package/fs/types/function/compare/proof.f.d.ts +1 -0
- package/fs/types/function/compare/{test.f.js → proof.f.js} +1 -1
- package/fs/types/function/operator/proof.f.d.ts +12 -0
- package/fs/types/function/operator/{test.f.js → proof.f.js} +11 -10
- package/fs/types/function/proof.f.d.ts +1 -0
- package/fs/types/function/{test.f.js → proof.f.js} +1 -1
- package/fs/types/list/{test.f.d.ts → proof.f.d.ts} +2 -2
- package/fs/types/list/{test.f.js → proof.f.js} +15 -1
- package/fs/types/map/proof.f.d.ts +4 -0
- package/fs/types/map/{test.f.js → proof.f.js} +1 -1
- package/fs/types/monoid/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/monoid/{test.f.js → proof.f.js} +1 -1
- package/fs/types/nibble_set/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/nibble_set/{test.f.js → proof.f.js} +1 -1
- package/fs/types/nominal/proof.f.d.ts +4 -0
- package/fs/types/nominal/{test.f.js → proof.f.js} +1 -1
- package/fs/types/nullable/module.f.d.ts +7 -0
- package/fs/types/nullable/module.f.js +7 -0
- package/fs/types/nullable/proof.f.d.ts +1 -0
- package/fs/types/nullable/{test.f.js → proof.f.js} +20 -3
- package/fs/types/number/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/number/{test.f.js → proof.f.js} +1 -1
- package/fs/types/object/module.f.js +2 -4
- package/fs/types/object/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/object/{test.f.js → proof.f.js} +1 -1
- package/fs/types/ordered_map/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/ordered_map/{test.f.js → proof.f.js} +1 -1
- package/fs/types/patricia_trie/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/patricia_trie/{test.f.js → proof.f.js} +2 -2
- package/fs/types/prime_field/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/prime_field/{test.f.js → proof.f.js} +1 -1
- package/fs/types/range/proof.f.d.ts +1 -0
- package/fs/types/range/{test.f.js → proof.f.js} +1 -1
- package/fs/types/range_map/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/range_map/{test.f.js → proof.f.js} +1 -1
- package/fs/types/result/proof.f.d.ts +5 -0
- package/fs/types/result/{test.f.js → proof.f.js} +18 -2
- package/fs/types/rtti/parse/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/rtti/parse/{test.f.js → proof.f.js} +1 -1
- package/fs/types/rtti/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/rtti/{test.f.js → proof.f.js} +1 -1
- package/fs/types/rtti/ts/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/rtti/ts/{test.f.js → proof.f.js} +1 -1
- package/fs/types/rtti/validate/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/rtti/validate/{test.f.js → proof.f.js} +1 -1
- package/fs/types/sorted_list/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/sorted_list/{test.f.js → proof.f.js} +1 -1
- package/fs/types/sorted_set/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/sorted_set/{test.f.js → proof.f.js} +1 -1
- package/fs/types/string/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/string/{test.f.js → proof.f.js} +1 -1
- package/fs/types/string_set/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/string_set/{test.f.js → proof.f.js} +1 -1
- package/fs/types/ts/module.f.d.ts +0 -1
- package/fs/types/ts/{test.f.d.ts → proof.f.d.ts} +20 -0
- package/fs/types/ts/{test.f.js → proof.f.js} +1 -0
- package/fs/types/uint8array/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/types/uint8array/{test.f.js → proof.f.js} +1 -1
- package/fs/website/proof.f.d.ts +3 -0
- package/fs/website/proof.f.js +9 -0
- package/issues/demo/sample/{test.f.js → proof.f.js} +1 -1
- package/issues/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/issues/{test.f.js → proof.f.js} +1 -1
- package/nanvm-lib/tests/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/nanvm-lib/tests/{test.f.js → proof.f.js} +1 -1
- package/nanvm-lib/tests/vm/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/nanvm-lib/tests/vm/{test.f.js → proof.f.js} +1 -1
- package/package.json +2 -2
- package/fs/base128/test.f.d.ts +0 -2
- package/fs/bnf/test.f.d.ts +0 -4
- package/fs/cas/test.f.d.ts +0 -2
- package/fs/cas/test.f.js +0 -1
- package/fs/dev/tf/scenarios/fail.fail.f.d.ts +0 -1
- package/fs/dev/tf/scenarios/fail.fail.f.js +0 -1
- package/fs/dev/tf/scenarios/return-value.pass.f.d.ts +0 -1
- package/fs/dev/tf/scenarios/return-value.pass.f.js +0 -2
- package/fs/dev/tf/scenarios/throw.pass.f.d.ts +0 -6
- package/fs/dev/version/test.f.d.ts +0 -4
- package/fs/fsm/test.f.d.ts +0 -5
- package/fs/path/test.f.d.ts +0 -3
- package/fs/text/ascii/test.f.d.ts +0 -4
- package/fs/text/sgr/test.f.d.ts +0 -2
- package/fs/types/btree/find/test.f.d.ts +0 -2
- package/fs/types/btree/remove/test.f.d.ts +0 -5
- package/fs/types/btree/set/test.f.d.ts +0 -2
- package/fs/types/function/compare/test.f.d.ts +0 -2
- package/fs/types/function/operator/test.f.d.ts +0 -10
- package/fs/types/function/test.f.d.ts +0 -2
- package/fs/types/map/test.f.d.ts +0 -5
- package/fs/types/nominal/test.f.d.ts +0 -5
- package/fs/types/nullable/test.f.d.ts +0 -2
- package/fs/types/range/test.f.d.ts +0 -2
- package/fs/types/result/test.f.d.ts +0 -2
- /package/fs/{dev/tf → emergent-testing}/all.test.d.ts +0 -0
- /package/fs/{dev/tf → emergent-testing}/all.test.js +0 -0
- /package/fs/{dev/tf → emergent-testing}/module.d.ts +0 -0
- /package/fs/{dev/tf → emergent-testing}/scenarios/all.d.ts +0 -0
- /package/fs/{dev/tf → emergent-testing}/scenarios/all.js +0 -0
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import { pure } from "
|
|
2
|
-
import { emptyState } from "
|
|
3
|
-
import { virtual } from "
|
|
4
|
-
import { assert, assertEq, todo } from "../module.f.js";
|
|
5
|
-
import { testAll, defaultReporter, fmtPath, fmtTerm, fmtImport, ghEscape, isInteger, isIdentifier, defaultTest, } from "./module.f.js";
|
|
1
|
+
import { pure } from "../types/effects/module.f.js";
|
|
2
|
+
import { emptyState } from "../types/effects/node/virtual/module.f.js";
|
|
3
|
+
import { virtual } from "../types/effects/node/virtual/module.f.js";
|
|
4
|
+
import { assert, assertEq, todo } from "../asserts/module.f.js";
|
|
5
|
+
import { testAll, defaultReporter, fmtPath, fmtTerm, fmtImport, ghEscape, isInteger, isIdentifier, registerModule, defaultTest, } from "./module.f.js";
|
|
6
|
+
import { run as mockRun } from "../types/effects/mock/module.f.js";
|
|
7
|
+
import { shouldLoad } from "../dev/module.f.js";
|
|
6
8
|
const makeReporter = () => {
|
|
7
9
|
const events = [];
|
|
8
10
|
const reporter = {
|
|
9
|
-
result: (file, path, r) => { events.push(['result', file, [...path], r]); return pure(undefined); },
|
|
11
|
+
result: (file, path, r, _throws) => { events.push(['result', file, [...path], r]); return pure(undefined); },
|
|
10
12
|
summary: (pass, fail, time) => { events.push(['summary', pass, fail, time]); return pure(undefined); },
|
|
11
13
|
test: defaultTest,
|
|
12
14
|
};
|
|
@@ -42,7 +44,7 @@ const runMain = (dir, github = false) => {
|
|
|
42
44
|
// flat object: two passing tests
|
|
43
45
|
export const flat = () => {
|
|
44
46
|
const [events, exit] = run({
|
|
45
|
-
'a.
|
|
47
|
+
'a.proof.f.ts': () => ({ proof: { a: ok0, b: ok1 } }),
|
|
46
48
|
});
|
|
47
49
|
assertEq(exit, 0);
|
|
48
50
|
const [e0, e1, e2] = events;
|
|
@@ -56,7 +58,7 @@ export const flat = () => {
|
|
|
56
58
|
// nested object: leaf tests carry the full path including the sub-tree key
|
|
57
59
|
export const nested = () => {
|
|
58
60
|
const [events, exit] = run({
|
|
59
|
-
'n.
|
|
61
|
+
'n.proof.f.ts': () => ({ proof: { math: { add: ok0, sub: ok0 } } }),
|
|
60
62
|
});
|
|
61
63
|
assertEq(exit, 0);
|
|
62
64
|
const [e0, e1, e2] = events;
|
|
@@ -70,7 +72,7 @@ export const nested = () => {
|
|
|
70
72
|
// throw key: tests inside 'throw' pass on error result
|
|
71
73
|
export const throwKey = () => {
|
|
72
74
|
const [events, exit] = run({
|
|
73
|
-
't.
|
|
75
|
+
't.proof.f.ts': () => ({ proof: { throw: { a: fail0 } } }),
|
|
74
76
|
});
|
|
75
77
|
assertEq(exit, 0);
|
|
76
78
|
const [e0, e1] = events;
|
|
@@ -83,7 +85,7 @@ export const throwKey = () => {
|
|
|
83
85
|
// throw key fails when test does not throw (returns ok in throw context)
|
|
84
86
|
export const throwKeyFail = () => {
|
|
85
87
|
const [events, exit] = run({
|
|
86
|
-
't.
|
|
88
|
+
't.proof.f.ts': () => ({ proof: { throw: { a: ok0 } } }),
|
|
87
89
|
});
|
|
88
90
|
assertEq(exit, 1);
|
|
89
91
|
const [e0, e1] = events;
|
|
@@ -95,7 +97,7 @@ export const throwKeyFail = () => {
|
|
|
95
97
|
// mixed pass/fail updates summary counts
|
|
96
98
|
export const mixedPassFail = () => {
|
|
97
99
|
const [events, exit] = run({
|
|
98
|
-
'm.
|
|
100
|
+
'm.proof.f.ts': () => ({ proof: { good: ok0, bad: fail0 } }),
|
|
99
101
|
});
|
|
100
102
|
assertEq(exit, 1);
|
|
101
103
|
const summary = events[events.length - 1];
|
|
@@ -108,11 +110,13 @@ export const mixedPassFail = () => {
|
|
|
108
110
|
export const returnValueSubTree = () => {
|
|
109
111
|
const inner = () => ({ result: ['ok', undefined], duration: 0 });
|
|
110
112
|
const [events, exit] = run({
|
|
111
|
-
'r.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
'r.proof.f.ts': () => ({
|
|
114
|
+
proof: {
|
|
115
|
+
outer: () => ({
|
|
116
|
+
result: ['ok', { inner }],
|
|
117
|
+
duration: 0,
|
|
118
|
+
}),
|
|
119
|
+
}
|
|
116
120
|
}),
|
|
117
121
|
});
|
|
118
122
|
// outer passes, then inner (from return value) also passes
|
|
@@ -126,7 +130,7 @@ export const returnValueSubTree = () => {
|
|
|
126
130
|
// integer-indexed array keys appear as numeric path segments
|
|
127
131
|
export const arrayKeys = () => {
|
|
128
132
|
const [events, exit] = run({
|
|
129
|
-
'a.
|
|
133
|
+
'a.proof.f.ts': () => ({ proof: { arr: [ok0, ok0] } }),
|
|
130
134
|
});
|
|
131
135
|
assertEq(exit, 0);
|
|
132
136
|
const passEvents = events.filter(e => e[0] === 'result');
|
|
@@ -134,22 +138,24 @@ export const arrayKeys = () => {
|
|
|
134
138
|
assertEq(passEvents[0][2][1], '0');
|
|
135
139
|
assertEq(passEvents[1][2][1], '1');
|
|
136
140
|
};
|
|
137
|
-
// non-
|
|
141
|
+
// non-proof files are skipped: plain `.ts` is not loaded; `.f.ts` without
|
|
142
|
+
// a `proof` export is loaded but produces no events
|
|
138
143
|
export const nonTestFilesSkipped = () => {
|
|
139
144
|
const [events, exit] = run({
|
|
140
|
-
'helper.ts': () => ({ a: ok0 }),
|
|
141
|
-
'
|
|
145
|
+
'helper.ts': () => ({ a: ok0 }), // not loaded (plain .ts)
|
|
146
|
+
'module.f.ts': () => ({ someExport: ok0 }), // loaded, no proof → skipped
|
|
147
|
+
'b.proof.f.ts': () => ({ proof: { x: ok0 } }), // loaded, has proof → runs
|
|
142
148
|
});
|
|
143
149
|
assertEq(exit, 0);
|
|
144
150
|
const results = events.filter(e => e[0] === 'result');
|
|
145
151
|
assertEq(results.length, 1);
|
|
146
|
-
assertEq(results[0][1], './b.
|
|
152
|
+
assertEq(results[0][1], './b.proof.f.ts');
|
|
147
153
|
};
|
|
148
154
|
// multiple test files each produce result events
|
|
149
155
|
export const multipleFiles = () => {
|
|
150
156
|
const [events, exit] = run({
|
|
151
|
-
'a.
|
|
152
|
-
'b.
|
|
157
|
+
'a.proof.f.ts': () => ({ proof: { x: ok0 } }),
|
|
158
|
+
'b.proof.f.ts': () => ({ proof: { y: ok0 } }),
|
|
153
159
|
});
|
|
154
160
|
assertEq(exit, 0);
|
|
155
161
|
const results = events.filter(e => e[0] === 'result');
|
|
@@ -164,51 +170,86 @@ export const throwByFunctionName = () => {
|
|
|
164
170
|
// const named = ({ throw: () => fail0() }).throw
|
|
165
171
|
const x = { throw: () => fail0() };
|
|
166
172
|
const [events, exit] = run({
|
|
167
|
-
't.
|
|
173
|
+
't.proof.f.ts': () => ({ proof: { here: x.throw } }),
|
|
168
174
|
});
|
|
169
175
|
assertEq(exit, 0);
|
|
170
176
|
const passEvents = events.filter(e => e[0] === 'result');
|
|
171
177
|
assertEq(passEvents.length, 1);
|
|
172
178
|
assertEq(passEvents[0][2][0], 'here');
|
|
173
179
|
};
|
|
174
|
-
//
|
|
180
|
+
// only the `proof` export is used; other module properties are ignored
|
|
175
181
|
export const namedExports = () => {
|
|
176
182
|
const [events, exit] = run({
|
|
177
|
-
'e.
|
|
183
|
+
'e.proof.f.ts': () => ({ proof: { a: ok0, b: ok0 }, other: ok0 }),
|
|
178
184
|
});
|
|
179
185
|
assertEq(exit, 0);
|
|
180
186
|
const passEvents = events.filter(e => e[0] === 'result');
|
|
181
|
-
assertEq(passEvents.length, 2);
|
|
182
|
-
assertEq(passEvents[0][2][0], '
|
|
183
|
-
assertEq(passEvents[1][2][0], '
|
|
187
|
+
assertEq(passEvents.length, 2); // `other` is ignored
|
|
188
|
+
assertEq(passEvents[0][2][0], 'a');
|
|
189
|
+
assertEq(passEvents[1][2][0], 'b');
|
|
184
190
|
};
|
|
185
191
|
// the default (non-GitHub) reporter formats module/pass/summary lines on stdout
|
|
186
192
|
export const defaultReporterOutput = () => {
|
|
187
193
|
const [stdout, stderr, exit] = runMain({
|
|
188
|
-
'a.
|
|
194
|
+
'a.proof.f.ts': () => ({ proof: { x: ok0 } }),
|
|
189
195
|
});
|
|
190
196
|
assertEq(exit, 0);
|
|
191
197
|
assertEq(stderr, '');
|
|
192
|
-
assertEq(stdout, 'import("./a.
|
|
198
|
+
assertEq(stdout, 'import("./a.proof.f.ts").proof.x(): ok, 0.0000 ms\n'
|
|
193
199
|
+ 'Number of tests: pass: 1, fail: 0, total: 1\n'
|
|
194
200
|
+ 'Time: 0.0000 ms\n');
|
|
195
201
|
};
|
|
196
202
|
// a failure on the non-GitHub reporter writes the error to stderr, not stdout
|
|
197
203
|
export const defaultReporterFailOutput = () => {
|
|
198
204
|
const [, stderr, exit] = runMain({
|
|
199
|
-
'a.
|
|
205
|
+
'a.proof.f.ts': () => ({ proof: { bad: fail0 } }),
|
|
200
206
|
});
|
|
201
207
|
assertEq(exit, 1);
|
|
202
|
-
assertEq(stderr, 'import("./a.
|
|
208
|
+
assertEq(stderr, 'import("./a.proof.f.ts").proof.bad(): error, 0.0000 ms\noops\n');
|
|
203
209
|
};
|
|
204
210
|
// the GitHub reporter emits an `::error` annotation with a percent-encoded
|
|
205
211
|
// title (the JSON path) and message
|
|
206
212
|
export const githubReporterOutput = () => {
|
|
207
213
|
const [, stderr, exit] = runMain({
|
|
208
|
-
's.
|
|
214
|
+
's.proof.f.ts': () => ({ proof: { 'a:b,c%d': fail0 } }),
|
|
209
215
|
}, true);
|
|
210
216
|
assertEq(exit, 1);
|
|
211
|
-
assertEq(stderr, '::error file=./s.
|
|
217
|
+
assertEq(stderr, '::error file=./s.proof.f.ts,line=1,title=import("./s.proof.f.ts").proof["a%3Ab%2Cc%25d"]()::oops\n');
|
|
218
|
+
};
|
|
219
|
+
// registerModule appends ' ...' for inline runners (Bun/Playwright).
|
|
220
|
+
// Uses a minimal synchronous mock for the Test/All/Await effect operations.
|
|
221
|
+
export const registerSuffixes = () => {
|
|
222
|
+
let runner;
|
|
223
|
+
const noopCtx = { test: (_n, _o, _f) => Promise.resolve() };
|
|
224
|
+
const makeRunner = () => mockRun({
|
|
225
|
+
test: (s, _ctx, name, _xf, _fn) => [[...s, name], undefined],
|
|
226
|
+
all: (s, ...effects) => {
|
|
227
|
+
let st = s;
|
|
228
|
+
const rs = [];
|
|
229
|
+
for (const e of effects) {
|
|
230
|
+
const [ns, r] = runner(st)(e);
|
|
231
|
+
st = ns;
|
|
232
|
+
rs.push(r);
|
|
233
|
+
}
|
|
234
|
+
return [st, rs];
|
|
235
|
+
},
|
|
236
|
+
await: (s, p) => [s, [p]],
|
|
237
|
+
});
|
|
238
|
+
runner = makeRunner();
|
|
239
|
+
const proof = {
|
|
240
|
+
ok: () => { },
|
|
241
|
+
throw: { a: () => { throw 'expected'; } },
|
|
242
|
+
};
|
|
243
|
+
// Node (star = ''): no suffixes
|
|
244
|
+
const [nodeNames] = runner([])(registerModule(noopCtx, './a.f.ts', proof, ''));
|
|
245
|
+
assertEq(nodeNames.length, 2);
|
|
246
|
+
assertEq(nodeNames[0], 'import("./a.f.ts").proof.ok()');
|
|
247
|
+
assertEq(nodeNames[1], 'import("./a.f.ts").proof.throw.a()');
|
|
248
|
+
// Bun/Playwright (star = ' ...'): ... on normal tests, path shows throw for throw-tests
|
|
249
|
+
const [inlineNames] = runner([])(registerModule(noopCtx, './a.f.ts', proof, ' ...'));
|
|
250
|
+
assertEq(inlineNames.length, 2);
|
|
251
|
+
assertEq(inlineNames[0], 'import("./a.f.ts").proof.ok() ...');
|
|
252
|
+
assertEq(inlineNames[1], 'import("./a.f.ts").proof.throw.a()');
|
|
212
253
|
};
|
|
213
254
|
// direct unit tests for the pure path-format helpers
|
|
214
255
|
export const helpers = {
|
|
@@ -229,12 +270,32 @@ export const helpers = {
|
|
|
229
270
|
assert(!isIdentifier('1a'));
|
|
230
271
|
assert(!isIdentifier('a-b'));
|
|
231
272
|
},
|
|
273
|
+
shouldLoad: () => {
|
|
274
|
+
// all .f.ts / .f.js — FS modules are safe to bulk-load
|
|
275
|
+
assert(shouldLoad('module.f.ts'));
|
|
276
|
+
assert(shouldLoad('module.f.js'));
|
|
277
|
+
assert(shouldLoad('a.proof.f.ts'));
|
|
278
|
+
assert(shouldLoad('dir/module.f.ts'));
|
|
279
|
+
// vanilla opt-in by filename
|
|
280
|
+
assert(shouldLoad('proof.ts'));
|
|
281
|
+
assert(shouldLoad('proof.js'));
|
|
282
|
+
assert(shouldLoad('proof.mts'));
|
|
283
|
+
assert(shouldLoad('proof.mjs'));
|
|
284
|
+
assert(shouldLoad('math.proof.ts'));
|
|
285
|
+
assert(shouldLoad('math.proof.js'));
|
|
286
|
+
assert(shouldLoad('math.proof.mts'));
|
|
287
|
+
assert(shouldLoad('dir/math.proof.ts'));
|
|
288
|
+
// non-FS, non-proof vanilla files are not loaded
|
|
289
|
+
assert(!shouldLoad('helper.ts'));
|
|
290
|
+
assert(!shouldLoad('module.ts'));
|
|
291
|
+
assert(!shouldLoad('proof.tsx'));
|
|
292
|
+
},
|
|
232
293
|
fmtImport: () => {
|
|
233
|
-
assertEq(fmtImport('./a.
|
|
234
|
-
assertEq(fmtImport('./a.
|
|
235
|
-
assertEq(fmtImport('./a.
|
|
236
|
-
assertEq(fmtImport('./a.
|
|
237
|
-
assertEq(fmtImport('./a.
|
|
294
|
+
assertEq(fmtImport('./a.proof.f.ts', []), 'import("./a.proof.f.ts").proof()');
|
|
295
|
+
assertEq(fmtImport('./a.proof.f.ts', ['math', 'add']), 'import("./a.proof.f.ts").proof.math.add()');
|
|
296
|
+
assertEq(fmtImport('./a.proof.f.ts', ['users', '3']), 'import("./a.proof.f.ts").proof.users[3]()');
|
|
297
|
+
assertEq(fmtImport('./a.proof.f.ts', ['x', 'hello world']), 'import("./a.proof.f.ts").proof.x["hello world"]()');
|
|
298
|
+
assertEq(fmtImport('./a.proof.f.ts', ['outer', null, 'inner']), 'import("./a.proof.f.ts").proof.outer().inner()');
|
|
238
299
|
},
|
|
239
300
|
fmtPath: () => {
|
|
240
301
|
assertEq(fmtPath([]), '');
|
|
@@ -257,3 +318,21 @@ export const helpers = {
|
|
|
257
318
|
assertEq(ghEscape('a%b:c,d'), 'a%25b%3Ac%2Cd');
|
|
258
319
|
},
|
|
259
320
|
};
|
|
321
|
+
export const proof = {
|
|
322
|
+
flat,
|
|
323
|
+
nested,
|
|
324
|
+
throwKey,
|
|
325
|
+
throwKeyFail,
|
|
326
|
+
mixedPassFail,
|
|
327
|
+
returnValueSubTree,
|
|
328
|
+
arrayKeys,
|
|
329
|
+
nonTestFilesSkipped,
|
|
330
|
+
multipleFiles,
|
|
331
|
+
throwByFunctionName,
|
|
332
|
+
namedExports,
|
|
333
|
+
defaultReporterOutput,
|
|
334
|
+
defaultReporterFailOutput,
|
|
335
|
+
githubReporterOutput,
|
|
336
|
+
registerSuffixes,
|
|
337
|
+
helpers
|
|
338
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// A test that returns a thenable (Promise-like object, not a real Promise).
|
|
2
|
+
// Per FunctionalScript convention, thenables are treated as plain values —
|
|
3
|
+
// not awaited. Both sandbox (fjs) and registerModule (node/bun/deno/playwright)
|
|
4
|
+
// must exit 0: the thenable object is walked as a sub-tree whose only key
|
|
5
|
+
// `then` is a function with parameters, so no leaf tests are found and the
|
|
6
|
+
// test trivially passes.
|
|
7
|
+
export const proof = {
|
|
8
|
+
thenableResolves: () => ({
|
|
9
|
+
then(resolve) { resolve(undefined); }
|
|
10
|
+
})
|
|
11
|
+
};
|
package/fs/fjs/module.f.js
CHANGED
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
import { compile } from "../djs/module.f.js";
|
|
7
|
-
import { main as testMain } from "../
|
|
7
|
+
import { main as testMain } from "../emergent-testing/module.f.js";
|
|
8
8
|
import { main as casMain } from "../cas/module.f.js";
|
|
9
|
-
import { import_,
|
|
10
|
-
import { pure } from "../types/effects/module.f.js";
|
|
9
|
+
import { import_, errorExit } from "../types/effects/node/module.f.js";
|
|
11
10
|
export const main = options => {
|
|
12
11
|
const [command, ...rest] = options.args;
|
|
13
12
|
switch (command) {
|
|
@@ -31,8 +30,8 @@ export const main = options => {
|
|
|
31
30
|
});
|
|
32
31
|
}
|
|
33
32
|
case undefined:
|
|
34
|
-
return
|
|
33
|
+
return errorExit('Error: command is required');
|
|
35
34
|
default:
|
|
36
|
-
return
|
|
35
|
+
return errorExit(`Error: Unknown command "${command}"`);
|
|
37
36
|
}
|
|
38
37
|
};
|
|
@@ -11,7 +11,7 @@ const fn = (f, name) => ({ [name]: f }[name]);
|
|
|
11
11
|
const withName = (name) =>
|
|
12
12
|
// translated into one command: define a `function [name]() { return undefined }`
|
|
13
13
|
Object.getOwnPropertyDescriptor({ [name]: () => undefined }, name).value;
|
|
14
|
-
export
|
|
14
|
+
export const proof = {
|
|
15
15
|
a: () => {
|
|
16
16
|
const x = f('1');
|
|
17
17
|
if (x !== '["1"]') {
|
package/fs/io/module.d.ts
CHANGED
|
@@ -4,6 +4,6 @@ import { type Result } from '../types/result/module.f.ts';
|
|
|
4
4
|
export declare const asyncImport: (v: string) => Promise<Module>;
|
|
5
5
|
export declare const tryCatch: <T>(f: () => T) => Result<T, unknown>;
|
|
6
6
|
export declare const io: Io;
|
|
7
|
-
export type NodeRun = (p: NodeProgram) => Promise<
|
|
7
|
+
export type NodeRun = (p: NodeProgram) => Promise<never>;
|
|
8
8
|
declare const effectRun: NodeRun;
|
|
9
9
|
export default effectRun;
|
package/fs/io/module.f.d.ts
CHANGED
|
@@ -74,7 +74,7 @@ export type Process = {
|
|
|
74
74
|
readonly stderr: Writable;
|
|
75
75
|
};
|
|
76
76
|
export type TryCatch = <T>(f: () => T) => Result<T, unknown>;
|
|
77
|
-
export type Sandbox = <T>(f: () => T) => SandboxResult<T
|
|
77
|
+
export type Sandbox = <T>(f: () => T) => Promise<SandboxResult<T>>;
|
|
78
78
|
export type Server = {
|
|
79
79
|
readonly listen: (port: number) => void;
|
|
80
80
|
};
|
|
@@ -120,6 +120,7 @@ export type Io = {
|
|
|
120
120
|
readonly bunTestContext: TestContext;
|
|
121
121
|
readonly playwrightTestContext: TestContext;
|
|
122
122
|
readonly engine: Engine;
|
|
123
|
+
readonly await: (p: unknown) => Promise<readonly [unknown]>;
|
|
123
124
|
};
|
|
124
125
|
export type App = (io: Io) => Promise<number>;
|
|
125
126
|
export type Run = (f: App) => Promise<never>;
|
|
@@ -129,5 +130,5 @@ export type Run = (f: App) => Promise<never>;
|
|
|
129
130
|
*/
|
|
130
131
|
export declare const run: (io: Io) => Run;
|
|
131
132
|
export type EffectToPromise = <T>(effect: Effect<NodeOp, T>) => Promise<T>;
|
|
132
|
-
export declare const fromIo: ({ fs: { promises: { mkdir, readFile, readdir, writeFile, rm, access } }, fetch, http: { createServer }, childProcess, asyncImport, now: ioNow, sandbox
|
|
133
|
+
export declare const fromIo: ({ fs: { promises: { mkdir, readFile, readdir, writeFile, rm, access } }, fetch, http: { createServer }, childProcess, asyncImport, now: ioNow, sandbox, write, await: awaitPromise, }: Io) => EffectToPromise;
|
|
133
134
|
export declare const runProgram: (io: Io) => (args: readonly string[]) => (program: NodeProgram) => Promise<number>;
|
package/fs/io/module.f.js
CHANGED
|
@@ -45,7 +45,7 @@ const collect = async (v) => {
|
|
|
45
45
|
}
|
|
46
46
|
return result;
|
|
47
47
|
};
|
|
48
|
-
export const fromIo = ({ fs: { promises: { mkdir, readFile, readdir, writeFile, rm, access } }, fetch, http: { createServer }, childProcess, asyncImport, now: ioNow, sandbox
|
|
48
|
+
export const fromIo = ({ fs: { promises: { mkdir, readFile, readdir, writeFile, rm, access } }, fetch, http: { createServer }, childProcess, asyncImport, now: ioNow, sandbox, write, await: awaitPromise, }) => {
|
|
49
49
|
const result = asyncRun({
|
|
50
50
|
all: async (...effects) => await Promise.all(effects.map(result)),
|
|
51
51
|
fetch: async (url) => tc(async () => {
|
|
@@ -95,8 +95,9 @@ export const fromIo = ({ fs: { promises: { mkdir, readFile, readdir, writeFile,
|
|
|
95
95
|
},
|
|
96
96
|
forever: () => new Promise(() => { }),
|
|
97
97
|
now: async () => ioNow(),
|
|
98
|
-
sandbox
|
|
99
|
-
|
|
98
|
+
sandbox,
|
|
99
|
+
await: awaitPromise,
|
|
100
|
+
write,
|
|
100
101
|
test: async (ctx, name, expectFailure, test) => ctx.test(name, { expectFailure }, async (t) => result(test(t))),
|
|
101
102
|
});
|
|
102
103
|
return result;
|
package/fs/io/module.js
CHANGED
|
@@ -12,7 +12,7 @@ import fs from 'node:fs';
|
|
|
12
12
|
import process from 'node:process';
|
|
13
13
|
import { concat } from "../path/module.f.js";
|
|
14
14
|
import { once } from 'node:events';
|
|
15
|
-
import {
|
|
15
|
+
import { runProgram } from "./module.f.js";
|
|
16
16
|
import { error, ok } from "../types/result/module.f.js";
|
|
17
17
|
import { fromVec } from "../types/uint8array/module.f.js";
|
|
18
18
|
import * as testContext from 'node:test';
|
|
@@ -35,12 +35,11 @@ const inlineTest = async (name, { expectFailure }, fn) => {
|
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
37
|
const inlineContext = { test: inlineTest };
|
|
38
|
-
const
|
|
39
|
-
test: (name, opts, fn) =>
|
|
40
|
-
};
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
};
|
|
38
|
+
const wrapInlineTest = (register) => ({
|
|
39
|
+
test: (name, opts, fn) => register(name, () => inlineTest(name, opts, fn))
|
|
40
|
+
});
|
|
41
|
+
const bunTestContext = wrapInlineTest(testContext.test);
|
|
42
|
+
const playwrightTestContext = wrapInlineTest(pwTest);
|
|
44
43
|
const prefix = 'file:///';
|
|
45
44
|
const { now } = Date;
|
|
46
45
|
/** Maps `WriteConsoles` names to the corresponding Node.js writable streams. */
|
|
@@ -76,6 +75,7 @@ export const tryCatch = f => {
|
|
|
76
75
|
return error(e);
|
|
77
76
|
}
|
|
78
77
|
};
|
|
78
|
+
const awaitPromise = async (p) => [p instanceof Promise ? await p : p];
|
|
79
79
|
export const io = {
|
|
80
80
|
console,
|
|
81
81
|
fs,
|
|
@@ -99,14 +99,18 @@ export const io = {
|
|
|
99
99
|
http,
|
|
100
100
|
childProcess,
|
|
101
101
|
now,
|
|
102
|
-
sandbox: (f) => {
|
|
102
|
+
sandbox: async (f) => {
|
|
103
103
|
let result;
|
|
104
104
|
let after;
|
|
105
105
|
const before = performance.now();
|
|
106
106
|
try {
|
|
107
|
-
|
|
107
|
+
let p = f();
|
|
108
108
|
after = performance.now();
|
|
109
|
-
|
|
109
|
+
if (p instanceof Promise) {
|
|
110
|
+
p = await p;
|
|
111
|
+
after = performance.now();
|
|
112
|
+
}
|
|
113
|
+
result = ok(p);
|
|
110
114
|
}
|
|
111
115
|
catch (e) {
|
|
112
116
|
after = performance.now();
|
|
@@ -115,10 +119,14 @@ export const io = {
|
|
|
115
119
|
return { result, duration: after - before };
|
|
116
120
|
},
|
|
117
121
|
write: (stream, data) => writeAll(streams[stream], fromVec(data)),
|
|
122
|
+
await: awaitPromise,
|
|
118
123
|
testContext,
|
|
119
124
|
bunTestContext,
|
|
120
125
|
playwrightTestContext,
|
|
121
126
|
engine: isPlaywright ? 'playwright' : 'Bun' in globalThis ? 'bun' : 'node',
|
|
122
127
|
};
|
|
123
|
-
const effectRun =
|
|
128
|
+
const effectRun = async (p) => {
|
|
129
|
+
const code = await runProgram(io)(io.process.argv.slice(2))(p);
|
|
130
|
+
return process.exit(code);
|
|
131
|
+
};
|
|
124
132
|
export default effectRun;
|
|
@@ -7,7 +7,7 @@ const tokenizeString = s => toArray(map(withoutMetada)(tokenize(stringToList(s))
|
|
|
7
7
|
const tokenizeStringWithMetadata = s => toArray(tokenize(stringToList(s))(''));
|
|
8
8
|
const stringify = stringifyAsTree(sort);
|
|
9
9
|
const withoutMetada = tokenWithMetada => tokenWithMetada.token;
|
|
10
|
-
export
|
|
10
|
+
export const proof = {
|
|
11
11
|
djs: [
|
|
12
12
|
() => {
|
|
13
13
|
const result = stringify(tokenizeString(''));
|