functionalscript 0.18.0 → 0.20.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/module.f.js +7 -8
- package/fs/asn.1/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/asn.1/{test.f.js → proof.f.js} +12 -13
- 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 +2 -12
- package/fs/cas/proof.f.d.ts +1 -0
- package/fs/cas/proof.f.js +1 -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/config/module.f.d.ts +4 -4
- package/fs/ci/config/module.f.js +4 -4
- package/fs/ci/node/module.f.js +12 -7
- package/fs/ci/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/ci/{test.f.js → proof.f.js} +1 -1
- 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/module.f.js +3 -3
- 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 -2
- package/fs/dev/module.f.js +38 -22
- package/fs/dev/{test.f.d.ts → proof.f.d.ts} +5 -2
- package/fs/dev/{test.f.js → proof.f.js} +25 -2
- package/fs/dev/tf/module.d.ts +1 -2
- package/fs/dev/tf/module.f.d.ts +70 -7
- package/fs/dev/tf/module.f.js +115 -27
- package/fs/dev/tf/module.js +4 -103
- package/fs/dev/tf/{test.f.d.ts → proof.f.d.ts} +26 -0
- package/fs/dev/tf/{test.f.js → proof.f.js} +85 -38
- package/fs/dev/tf/scenarios/all.d.ts +1 -0
- package/fs/dev/tf/scenarios/all.js +3 -0
- package/fs/dev/tf/scenarios/async-subtests.fail.d.ts +4 -0
- package/fs/dev/tf/scenarios/async-subtests.fail.js +7 -0
- package/fs/dev/tf/scenarios/async-subtests.pass.d.ts +4 -0
- package/fs/dev/tf/scenarios/async-subtests.pass.js +7 -0
- package/fs/dev/tf/scenarios/async.fail.d.ts +1 -0
- package/fs/dev/tf/scenarios/async.fail.js +4 -0
- package/fs/dev/tf/scenarios/async.pass.d.ts +1 -0
- package/fs/dev/tf/scenarios/async.pass.js +3 -0
- package/fs/dev/tf/scenarios/fail.fail.f.d.ts +1 -0
- package/fs/dev/tf/scenarios/fail.fail.f.js +1 -0
- package/fs/dev/tf/scenarios/return-value.pass.f.d.ts +1 -0
- package/fs/dev/tf/scenarios/return-value.pass.f.js +2 -0
- package/fs/dev/tf/scenarios/thenable.pass.d.ts +3 -0
- package/fs/dev/tf/scenarios/thenable.pass.js +9 -0
- package/fs/dev/tf/scenarios/thenable2.pass.f.d.ts +3 -0
- package/fs/dev/tf/scenarios/thenable2.pass.f.js +3 -0
- package/fs/{bnf/test.f.d.ts → dev/tf/scenarios/throw.pass.f.d.ts} +3 -1
- package/fs/dev/tf/scenarios/throw.pass.f.js +3 -0
- 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/{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/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 +8 -3
- package/fs/io/module.f.js +12 -12
- package/fs/io/module.js +43 -5
- 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 +3 -4
- package/fs/sul/id/{test.f.d.ts → proof.f.d.ts} +1 -2
- package/fs/sul/id/{test.f.js → proof.f.js} +1 -1
- 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} +1 -1
- package/fs/sul/level/literal/module.f.js +3 -3
- 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} +1 -1
- 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/proof.f.js +23 -0
- 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/{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/module.f.d.ts +9 -4
- package/fs/types/bit_vec/module.f.js +7 -9
- 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/module.f.d.ts +1 -1
- package/fs/types/btree/remove/module.f.js +7 -2
- 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/module.f.d.ts +1 -1
- package/fs/types/btree/set/module.f.js +7 -2
- 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 +9 -0
- package/fs/types/btree/types/module.f.js +9 -1
- 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 +66 -4
- package/fs/types/effects/node/module.f.js +5 -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.d.ts +2 -1
- package/fs/types/effects/node/virtual/module.f.js +2 -0
- 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} +1 -2
- package/fs/types/list/{test.f.js → proof.f.js} +1 -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/proof.f.d.ts +1 -0
- package/fs/types/nullable/{test.f.js → proof.f.js} +11 -2
- 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/{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} +1 -1
- 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/{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/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 +5 -5
- package/fs/base128/test.f.d.ts +0 -2
- package/fs/cas/test.f.d.ts +0 -2
- package/fs/cas/test.f.js +0 -1
- 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/text/sgr/test.f.js +0 -8
- 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
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { pure } from "../../types/effects/module.f.js";
|
|
2
2
|
import { emptyState } from "../../types/effects/node/virtual/module.f.js";
|
|
3
3
|
import { virtual } from "../../types/effects/node/virtual/module.f.js";
|
|
4
|
-
import { assert, assertEq } from "../module.f.js";
|
|
5
|
-
import {
|
|
4
|
+
import { assert, assertEq, todo } from "../module.f.js";
|
|
5
|
+
import { testAll, defaultReporter, fmtPath, fmtTerm, fmtImport, ghEscape, isInteger, isIdentifier, defaultTest, } from "./module.f.js";
|
|
6
|
+
import { shouldLoad } from "../module.f.js";
|
|
6
7
|
const makeReporter = () => {
|
|
7
8
|
const events = [];
|
|
8
9
|
const reporter = {
|
|
@@ -12,10 +13,15 @@ const makeReporter = () => {
|
|
|
12
13
|
};
|
|
13
14
|
return [reporter, () => events];
|
|
14
15
|
};
|
|
16
|
+
const noopTestContext = { test: todo };
|
|
15
17
|
const options = (initCwd, github = false) => ({
|
|
16
18
|
args: [],
|
|
17
19
|
env: { INIT_CWD: initCwd, ...(github ? { GITHUB_ACTION: 'true' } : {}) },
|
|
18
20
|
std: { stdout: { isTTY: false }, stderr: { isTTY: false } },
|
|
21
|
+
testContext: noopTestContext,
|
|
22
|
+
bunTestContext: noopTestContext,
|
|
23
|
+
playwrightTestContext: noopTestContext,
|
|
24
|
+
engine: 'node',
|
|
19
25
|
});
|
|
20
26
|
const ok0 = () => ({ result: ['ok', undefined], duration: 0 });
|
|
21
27
|
const fail0 = () => ({ result: ['error', 'oops'], duration: 0 });
|
|
@@ -23,7 +29,7 @@ const ok1 = () => ({ result: ['ok', undefined], duration: 1 });
|
|
|
23
29
|
const run = (dir, initCwd = '.') => {
|
|
24
30
|
const [reporter, getEvents] = makeReporter();
|
|
25
31
|
const state = { ...emptyState, root: dir };
|
|
26
|
-
const [, exitCode] = virtual(state)(
|
|
32
|
+
const [, exitCode] = virtual(state)(testAll(reporter)(options(initCwd)));
|
|
27
33
|
return [getEvents(), exitCode];
|
|
28
34
|
};
|
|
29
35
|
// Runs the real `defaultReporter` and returns its captured stdout/stderr so the
|
|
@@ -31,13 +37,13 @@ const run = (dir, initCwd = '.') => {
|
|
|
31
37
|
const runMain = (dir, github = false) => {
|
|
32
38
|
const state = { ...emptyState, root: dir };
|
|
33
39
|
const opts = options('.', github);
|
|
34
|
-
const [finalState, exitCode] = virtual(state)(
|
|
40
|
+
const [finalState, exitCode] = virtual(state)(testAll(defaultReporter(opts))(opts));
|
|
35
41
|
return [finalState.stdout, finalState.stderr, exitCode];
|
|
36
42
|
};
|
|
37
43
|
// flat object: two passing tests
|
|
38
44
|
export const flat = () => {
|
|
39
45
|
const [events, exit] = run({
|
|
40
|
-
'a.
|
|
46
|
+
'a.proof.f.ts': () => ({ proof: { a: ok0, b: ok1 } }),
|
|
41
47
|
});
|
|
42
48
|
assertEq(exit, 0);
|
|
43
49
|
const [e0, e1, e2] = events;
|
|
@@ -51,7 +57,7 @@ export const flat = () => {
|
|
|
51
57
|
// nested object: leaf tests carry the full path including the sub-tree key
|
|
52
58
|
export const nested = () => {
|
|
53
59
|
const [events, exit] = run({
|
|
54
|
-
'n.
|
|
60
|
+
'n.proof.f.ts': () => ({ proof: { math: { add: ok0, sub: ok0 } } }),
|
|
55
61
|
});
|
|
56
62
|
assertEq(exit, 0);
|
|
57
63
|
const [e0, e1, e2] = events;
|
|
@@ -65,7 +71,7 @@ export const nested = () => {
|
|
|
65
71
|
// throw key: tests inside 'throw' pass on error result
|
|
66
72
|
export const throwKey = () => {
|
|
67
73
|
const [events, exit] = run({
|
|
68
|
-
't.
|
|
74
|
+
't.proof.f.ts': () => ({ proof: { throw: { a: fail0 } } }),
|
|
69
75
|
});
|
|
70
76
|
assertEq(exit, 0);
|
|
71
77
|
const [e0, e1] = events;
|
|
@@ -78,7 +84,7 @@ export const throwKey = () => {
|
|
|
78
84
|
// throw key fails when test does not throw (returns ok in throw context)
|
|
79
85
|
export const throwKeyFail = () => {
|
|
80
86
|
const [events, exit] = run({
|
|
81
|
-
't.
|
|
87
|
+
't.proof.f.ts': () => ({ proof: { throw: { a: ok0 } } }),
|
|
82
88
|
});
|
|
83
89
|
assertEq(exit, 1);
|
|
84
90
|
const [e0, e1] = events;
|
|
@@ -90,7 +96,7 @@ export const throwKeyFail = () => {
|
|
|
90
96
|
// mixed pass/fail updates summary counts
|
|
91
97
|
export const mixedPassFail = () => {
|
|
92
98
|
const [events, exit] = run({
|
|
93
|
-
'm.
|
|
99
|
+
'm.proof.f.ts': () => ({ proof: { good: ok0, bad: fail0 } }),
|
|
94
100
|
});
|
|
95
101
|
assertEq(exit, 1);
|
|
96
102
|
const summary = events[events.length - 1];
|
|
@@ -103,11 +109,13 @@ export const mixedPassFail = () => {
|
|
|
103
109
|
export const returnValueSubTree = () => {
|
|
104
110
|
const inner = () => ({ result: ['ok', undefined], duration: 0 });
|
|
105
111
|
const [events, exit] = run({
|
|
106
|
-
'r.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
112
|
+
'r.proof.f.ts': () => ({
|
|
113
|
+
proof: {
|
|
114
|
+
outer: () => ({
|
|
115
|
+
result: ['ok', { inner }],
|
|
116
|
+
duration: 0,
|
|
117
|
+
}),
|
|
118
|
+
}
|
|
111
119
|
}),
|
|
112
120
|
});
|
|
113
121
|
// outer passes, then inner (from return value) also passes
|
|
@@ -121,7 +129,7 @@ export const returnValueSubTree = () => {
|
|
|
121
129
|
// integer-indexed array keys appear as numeric path segments
|
|
122
130
|
export const arrayKeys = () => {
|
|
123
131
|
const [events, exit] = run({
|
|
124
|
-
'a.
|
|
132
|
+
'a.proof.f.ts': () => ({ proof: { arr: [ok0, ok0] } }),
|
|
125
133
|
});
|
|
126
134
|
assertEq(exit, 0);
|
|
127
135
|
const passEvents = events.filter(e => e[0] === 'result');
|
|
@@ -129,22 +137,24 @@ export const arrayKeys = () => {
|
|
|
129
137
|
assertEq(passEvents[0][2][1], '0');
|
|
130
138
|
assertEq(passEvents[1][2][1], '1');
|
|
131
139
|
};
|
|
132
|
-
// non-
|
|
140
|
+
// non-proof files are skipped: plain `.ts` is not loaded; `.f.ts` without
|
|
141
|
+
// a `proof` export is loaded but produces no events
|
|
133
142
|
export const nonTestFilesSkipped = () => {
|
|
134
143
|
const [events, exit] = run({
|
|
135
|
-
'helper.ts': () => ({ a: ok0 }),
|
|
136
|
-
'
|
|
144
|
+
'helper.ts': () => ({ a: ok0 }), // not loaded (plain .ts)
|
|
145
|
+
'module.f.ts': () => ({ someExport: ok0 }), // loaded, no proof → skipped
|
|
146
|
+
'b.proof.f.ts': () => ({ proof: { x: ok0 } }), // loaded, has proof → runs
|
|
137
147
|
});
|
|
138
148
|
assertEq(exit, 0);
|
|
139
149
|
const results = events.filter(e => e[0] === 'result');
|
|
140
150
|
assertEq(results.length, 1);
|
|
141
|
-
assertEq(results[0][1], './b.
|
|
151
|
+
assertEq(results[0][1], './b.proof.f.ts');
|
|
142
152
|
};
|
|
143
153
|
// multiple test files each produce result events
|
|
144
154
|
export const multipleFiles = () => {
|
|
145
155
|
const [events, exit] = run({
|
|
146
|
-
'a.
|
|
147
|
-
'b.
|
|
156
|
+
'a.proof.f.ts': () => ({ proof: { x: ok0 } }),
|
|
157
|
+
'b.proof.f.ts': () => ({ proof: { y: ok0 } }),
|
|
148
158
|
});
|
|
149
159
|
assertEq(exit, 0);
|
|
150
160
|
const results = events.filter(e => e[0] === 'result');
|
|
@@ -159,51 +169,51 @@ export const throwByFunctionName = () => {
|
|
|
159
169
|
// const named = ({ throw: () => fail0() }).throw
|
|
160
170
|
const x = { throw: () => fail0() };
|
|
161
171
|
const [events, exit] = run({
|
|
162
|
-
't.
|
|
172
|
+
't.proof.f.ts': () => ({ proof: { here: x.throw } }),
|
|
163
173
|
});
|
|
164
174
|
assertEq(exit, 0);
|
|
165
175
|
const passEvents = events.filter(e => e[0] === 'result');
|
|
166
176
|
assertEq(passEvents.length, 1);
|
|
167
177
|
assertEq(passEvents[0][2][0], 'here');
|
|
168
178
|
};
|
|
169
|
-
//
|
|
179
|
+
// only the `proof` export is used; other module properties are ignored
|
|
170
180
|
export const namedExports = () => {
|
|
171
181
|
const [events, exit] = run({
|
|
172
|
-
'e.
|
|
182
|
+
'e.proof.f.ts': () => ({ proof: { a: ok0, b: ok0 }, other: ok0 }),
|
|
173
183
|
});
|
|
174
184
|
assertEq(exit, 0);
|
|
175
185
|
const passEvents = events.filter(e => e[0] === 'result');
|
|
176
|
-
assertEq(passEvents.length, 2);
|
|
177
|
-
assertEq(passEvents[0][2][0], '
|
|
178
|
-
assertEq(passEvents[1][2][0], '
|
|
186
|
+
assertEq(passEvents.length, 2); // `other` is ignored
|
|
187
|
+
assertEq(passEvents[0][2][0], 'a');
|
|
188
|
+
assertEq(passEvents[1][2][0], 'b');
|
|
179
189
|
};
|
|
180
190
|
// the default (non-GitHub) reporter formats module/pass/summary lines on stdout
|
|
181
191
|
export const defaultReporterOutput = () => {
|
|
182
192
|
const [stdout, stderr, exit] = runMain({
|
|
183
|
-
'a.
|
|
193
|
+
'a.proof.f.ts': () => ({ proof: { x: ok0 } }),
|
|
184
194
|
});
|
|
185
195
|
assertEq(exit, 0);
|
|
186
196
|
assertEq(stderr, '');
|
|
187
|
-
assertEq(stdout, 'import("./a.
|
|
197
|
+
assertEq(stdout, 'import("./a.proof.f.ts").proof.x(): ok, 0.0000 ms\n'
|
|
188
198
|
+ 'Number of tests: pass: 1, fail: 0, total: 1\n'
|
|
189
199
|
+ 'Time: 0.0000 ms\n');
|
|
190
200
|
};
|
|
191
201
|
// a failure on the non-GitHub reporter writes the error to stderr, not stdout
|
|
192
202
|
export const defaultReporterFailOutput = () => {
|
|
193
203
|
const [, stderr, exit] = runMain({
|
|
194
|
-
'a.
|
|
204
|
+
'a.proof.f.ts': () => ({ proof: { bad: fail0 } }),
|
|
195
205
|
});
|
|
196
206
|
assertEq(exit, 1);
|
|
197
|
-
assertEq(stderr, 'import("./a.
|
|
207
|
+
assertEq(stderr, 'import("./a.proof.f.ts").proof.bad(): error, 0.0000 ms\noops\n');
|
|
198
208
|
};
|
|
199
209
|
// the GitHub reporter emits an `::error` annotation with a percent-encoded
|
|
200
210
|
// title (the JSON path) and message
|
|
201
211
|
export const githubReporterOutput = () => {
|
|
202
212
|
const [, stderr, exit] = runMain({
|
|
203
|
-
's.
|
|
213
|
+
's.proof.f.ts': () => ({ proof: { 'a:b,c%d': fail0 } }),
|
|
204
214
|
}, true);
|
|
205
215
|
assertEq(exit, 1);
|
|
206
|
-
assertEq(stderr, '::error file=./s.
|
|
216
|
+
assertEq(stderr, '::error file=./s.proof.f.ts,line=1,title=import("./s.proof.f.ts").proof["a%3Ab%2Cc%25d"]()::oops\n');
|
|
207
217
|
};
|
|
208
218
|
// direct unit tests for the pure path-format helpers
|
|
209
219
|
export const helpers = {
|
|
@@ -224,12 +234,32 @@ export const helpers = {
|
|
|
224
234
|
assert(!isIdentifier('1a'));
|
|
225
235
|
assert(!isIdentifier('a-b'));
|
|
226
236
|
},
|
|
237
|
+
shouldLoad: () => {
|
|
238
|
+
// all .f.ts / .f.js — FS modules are safe to bulk-load
|
|
239
|
+
assert(shouldLoad('module.f.ts'));
|
|
240
|
+
assert(shouldLoad('module.f.js'));
|
|
241
|
+
assert(shouldLoad('a.proof.f.ts'));
|
|
242
|
+
assert(shouldLoad('dir/module.f.ts'));
|
|
243
|
+
// vanilla opt-in by filename
|
|
244
|
+
assert(shouldLoad('proof.ts'));
|
|
245
|
+
assert(shouldLoad('proof.js'));
|
|
246
|
+
assert(shouldLoad('proof.mts'));
|
|
247
|
+
assert(shouldLoad('proof.mjs'));
|
|
248
|
+
assert(shouldLoad('math.proof.ts'));
|
|
249
|
+
assert(shouldLoad('math.proof.js'));
|
|
250
|
+
assert(shouldLoad('math.proof.mts'));
|
|
251
|
+
assert(shouldLoad('dir/math.proof.ts'));
|
|
252
|
+
// non-FS, non-proof vanilla files are not loaded
|
|
253
|
+
assert(!shouldLoad('helper.ts'));
|
|
254
|
+
assert(!shouldLoad('module.ts'));
|
|
255
|
+
assert(!shouldLoad('proof.tsx'));
|
|
256
|
+
},
|
|
227
257
|
fmtImport: () => {
|
|
228
|
-
assertEq(fmtImport('./a.
|
|
229
|
-
assertEq(fmtImport('./a.
|
|
230
|
-
assertEq(fmtImport('./a.
|
|
231
|
-
assertEq(fmtImport('./a.
|
|
232
|
-
assertEq(fmtImport('./a.
|
|
258
|
+
assertEq(fmtImport('./a.proof.f.ts', []), 'import("./a.proof.f.ts").proof()');
|
|
259
|
+
assertEq(fmtImport('./a.proof.f.ts', ['math', 'add']), 'import("./a.proof.f.ts").proof.math.add()');
|
|
260
|
+
assertEq(fmtImport('./a.proof.f.ts', ['users', '3']), 'import("./a.proof.f.ts").proof.users[3]()');
|
|
261
|
+
assertEq(fmtImport('./a.proof.f.ts', ['x', 'hello world']), 'import("./a.proof.f.ts").proof.x["hello world"]()');
|
|
262
|
+
assertEq(fmtImport('./a.proof.f.ts', ['outer', null, 'inner']), 'import("./a.proof.f.ts").proof.outer().inner()');
|
|
233
263
|
},
|
|
234
264
|
fmtPath: () => {
|
|
235
265
|
assertEq(fmtPath([]), '');
|
|
@@ -252,3 +282,20 @@ export const helpers = {
|
|
|
252
282
|
assertEq(ghEscape('a%b:c,d'), 'a%25b%3Ac%2Cd');
|
|
253
283
|
},
|
|
254
284
|
};
|
|
285
|
+
export const proof = {
|
|
286
|
+
flat,
|
|
287
|
+
nested,
|
|
288
|
+
throwKey,
|
|
289
|
+
throwKeyFail,
|
|
290
|
+
mixedPassFail,
|
|
291
|
+
returnValueSubTree,
|
|
292
|
+
arrayKeys,
|
|
293
|
+
nonTestFilesSkipped,
|
|
294
|
+
multipleFiles,
|
|
295
|
+
throwByFunctionName,
|
|
296
|
+
namedExports,
|
|
297
|
+
defaultReporterOutput,
|
|
298
|
+
defaultReporterFailOutput,
|
|
299
|
+
githubReporterOutput,
|
|
300
|
+
helpers
|
|
301
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const sleep_fail: () => Promise<never>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const sleep: () => Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const failing: () => never;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const failing = () => { throw 'intentional failure'; };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const outer: () => unknown;
|
|
@@ -0,0 +1,9 @@
|
|
|
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 thenableResolves = () => ({
|
|
8
|
+
then(resolve) { resolve(undefined); }
|
|
9
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { sort } from "../../types/object/module.f.js";
|
|
2
2
|
import { run } from "./module.f.js";
|
|
3
3
|
import { stringifyAsTree } from "../serializer/module.f.js";
|
|
4
|
-
export
|
|
4
|
+
export const proof = {
|
|
5
5
|
test: () => {
|
|
6
6
|
const djs = run([1])([]);
|
|
7
7
|
const result = stringifyAsTree(sort)(djs);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare const
|
|
1
|
+
export declare const proof: {
|
|
2
2
|
valid: (() => void)[];
|
|
3
3
|
invalid: (() => void)[];
|
|
4
4
|
errorMetadata: (() => void)[];
|
|
@@ -11,4 +11,3 @@ declare const _default: {
|
|
|
11
11
|
invalidWithArgs: (() => void)[];
|
|
12
12
|
comments: (() => void)[];
|
|
13
13
|
};
|
|
14
|
-
export default _default;
|
|
@@ -7,7 +7,7 @@ import { stringifyAsTree } from "../serializer/module.f.js";
|
|
|
7
7
|
import { stringify } from "../../json/module.f.js";
|
|
8
8
|
const tokenizeString = s => toArray(tokenize(stringToList(s))(''));
|
|
9
9
|
const stringifyDjsModule = stringifyAsTree(sort);
|
|
10
|
-
export
|
|
10
|
+
export const proof = {
|
|
11
11
|
valid: [
|
|
12
12
|
() => {
|
|
13
13
|
const tokenList = tokenizeString('export default null');
|
|
@@ -7,11 +7,11 @@ import type { Unknown } from '../module.f.ts';
|
|
|
7
7
|
import type { Entry as ObjectEntry } from '../../types/object/module.f.ts';
|
|
8
8
|
import { type List } from '../../types/list/module.f.ts';
|
|
9
9
|
export declare const undefinedSerialize: string[];
|
|
10
|
-
type RefCounter = [number, number
|
|
10
|
+
type RefCounter = readonly [number, number];
|
|
11
11
|
type Entry = ObjectEntry<Unknown>;
|
|
12
12
|
type Entries = List<Entry>;
|
|
13
13
|
type MapEntries = (entries: Entries) => Entries;
|
|
14
|
-
type Refs =
|
|
14
|
+
type Refs = ReadonlyMap<Unknown, RefCounter>;
|
|
15
15
|
export declare const serializeWithoutConst: (mapEntries: MapEntries) => (value: Unknown) => List<string>;
|
|
16
16
|
export declare const stringify: (sort: MapEntries) => (djs: Unknown) => string;
|
|
17
17
|
export declare const stringifyAsTree: (mapEntries: MapEntries) => (value: Unknown) => string;
|
|
@@ -7,88 +7,47 @@ import { serialize as bigintSerialize } from "../../types/bigint/module.f.js";
|
|
|
7
7
|
import { objectWrap, arrayWrap, stringSerialize, numberSerialize, nullSerialize, boolSerialize } from "../../json/serializer/module.f.js";
|
|
8
8
|
const colon = [':'];
|
|
9
9
|
export const undefinedSerialize = ['undefined'];
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return getConstantSelf(djs)(state);
|
|
19
|
-
}
|
|
20
|
-
default: {
|
|
21
|
-
if (djs === null) {
|
|
22
|
-
return state;
|
|
23
|
-
}
|
|
24
|
-
if (djs === undefined) {
|
|
25
|
-
return state;
|
|
26
|
-
}
|
|
27
|
-
if (djs instanceof Array) {
|
|
28
|
-
return getConstantSelf(djs)(fold(getConstantsOp)(state)(djs));
|
|
29
|
-
}
|
|
30
|
-
return getConstantSelf(djs)(fold(getConstantsOp)(state)(map(entryValue)(entries(djs))));
|
|
10
|
+
const getConstants = refs => {
|
|
11
|
+
const checkSelf = djs => state => {
|
|
12
|
+
const refCounter = refs.get(djs);
|
|
13
|
+
if (refCounter !== undefined && refCounter[1] > 1 && !state.added.has(djs)) {
|
|
14
|
+
return {
|
|
15
|
+
added: new Set([...state.added, djs]),
|
|
16
|
+
consts: { head: state.consts, tail: [djs] }
|
|
17
|
+
};
|
|
31
18
|
}
|
|
32
|
-
|
|
33
|
-
};
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
const refCounter = refs.get(djs);
|
|
37
|
-
if (refCounter !== undefined && refCounter[1] > 1 && !refCounter[2]) {
|
|
38
|
-
refCounter[2] = true;
|
|
39
|
-
refs.set(djs, refCounter);
|
|
40
|
-
return { refs, consts: { head: state.consts, tail: [djs] } };
|
|
41
|
-
}
|
|
42
|
-
return state;
|
|
43
|
-
};
|
|
44
|
-
const getConstants = djs => refs => {
|
|
45
|
-
return getConstantsOp(djs)(refs);
|
|
46
|
-
};
|
|
47
|
-
const entryValue = kv => kv[1];
|
|
48
|
-
export const serializeWithoutConst = sort => {
|
|
49
|
-
const propertySerialize = ([k, v]) => flat([
|
|
50
|
-
stringSerialize(k),
|
|
51
|
-
colon,
|
|
52
|
-
f(v)
|
|
53
|
-
]);
|
|
54
|
-
const mapPropertySerialize = map(propertySerialize);
|
|
55
|
-
const objectSerialize = fn(entries)
|
|
56
|
-
.map(sort)
|
|
57
|
-
.map(mapPropertySerialize)
|
|
58
|
-
.map(objectWrap)
|
|
59
|
-
.result;
|
|
60
|
-
const f = value => {
|
|
61
|
-
switch (typeof value) {
|
|
19
|
+
return state;
|
|
20
|
+
};
|
|
21
|
+
const op = djs => state => {
|
|
22
|
+
switch (typeof djs) {
|
|
62
23
|
case 'boolean': {
|
|
63
|
-
return
|
|
64
|
-
}
|
|
65
|
-
case 'number': {
|
|
66
|
-
return numberSerialize(value);
|
|
67
|
-
}
|
|
68
|
-
case 'string': {
|
|
69
|
-
return stringSerialize(value);
|
|
24
|
+
return state;
|
|
70
25
|
}
|
|
26
|
+
case 'number':
|
|
27
|
+
case 'string':
|
|
71
28
|
case 'bigint': {
|
|
72
|
-
return
|
|
29
|
+
return checkSelf(djs)(state);
|
|
73
30
|
}
|
|
74
31
|
default: {
|
|
75
|
-
if (
|
|
76
|
-
return
|
|
32
|
+
if (djs === null) {
|
|
33
|
+
return state;
|
|
77
34
|
}
|
|
78
|
-
if (
|
|
79
|
-
return
|
|
35
|
+
if (djs === undefined) {
|
|
36
|
+
return state;
|
|
80
37
|
}
|
|
81
|
-
if (
|
|
82
|
-
return
|
|
38
|
+
if (djs instanceof Array) {
|
|
39
|
+
return checkSelf(djs)(fold(op)(state)(djs));
|
|
83
40
|
}
|
|
84
|
-
return
|
|
41
|
+
return checkSelf(djs)(fold(op)(state)(map(entryValue)(entries(djs))));
|
|
85
42
|
}
|
|
86
43
|
}
|
|
87
44
|
};
|
|
88
|
-
const
|
|
89
|
-
return
|
|
45
|
+
const init = { added: new Set(), consts: [] };
|
|
46
|
+
return djs => op(djs)(init).consts;
|
|
90
47
|
};
|
|
91
|
-
const
|
|
48
|
+
const entryValue = kv => kv[1];
|
|
49
|
+
const noRef = () => null;
|
|
50
|
+
const buildSerialize = refLookup => sort => {
|
|
92
51
|
const propertySerialize = ([k, v]) => flat([
|
|
93
52
|
stringSerialize(k),
|
|
94
53
|
colon,
|
|
@@ -101,11 +60,9 @@ const serializeWithConst = sort => refs => root => {
|
|
|
101
60
|
.map(objectWrap)
|
|
102
61
|
.result;
|
|
103
62
|
const f = value => {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
return [`c${refCounter[0]}`];
|
|
108
|
-
}
|
|
63
|
+
const ref = refLookup(value);
|
|
64
|
+
if (ref !== null) {
|
|
65
|
+
return ref;
|
|
109
66
|
}
|
|
110
67
|
switch (typeof value) {
|
|
111
68
|
case 'boolean': {
|
|
@@ -137,6 +94,17 @@ const serializeWithConst = sort => refs => root => {
|
|
|
137
94
|
const arraySerialize = compose(map(f))(arrayWrap);
|
|
138
95
|
return f;
|
|
139
96
|
};
|
|
97
|
+
export const serializeWithoutConst = buildSerialize(noRef);
|
|
98
|
+
const serializeWithConst = sort => refs => root => buildSerialize(value => {
|
|
99
|
+
if (value === root) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
const refCounter = refs.get(value);
|
|
103
|
+
if (refCounter !== undefined && refCounter[1] > 1) {
|
|
104
|
+
return [`c${refCounter[0]}`];
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
})(sort);
|
|
140
108
|
const countRefsOp = djs => refs => {
|
|
141
109
|
switch (typeof djs) {
|
|
142
110
|
case 'boolean':
|
|
@@ -167,14 +135,14 @@ const countRefsOp = djs => refs => {
|
|
|
167
135
|
};
|
|
168
136
|
const addRef = djs => refs => {
|
|
169
137
|
const refCounter = refs.get(djs);
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
return
|
|
138
|
+
const newCounter = refCounter === undefined
|
|
139
|
+
? [refs.size, 1]
|
|
140
|
+
: [refCounter[0], refCounter[1] + 1];
|
|
141
|
+
return new Map([...refs, [djs, newCounter]]);
|
|
174
142
|
};
|
|
175
143
|
export const stringify = sort => djs => {
|
|
176
144
|
const refs = countRefs(djs);
|
|
177
|
-
const consts = getConstants(
|
|
145
|
+
const consts = getConstants(refs)(djs);
|
|
178
146
|
const constSerialize = entry => {
|
|
179
147
|
const refCounter = refs.get(entry);
|
|
180
148
|
if (refCounter === undefined) {
|