functionalscript 0.8.0 → 0.8.2
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/bnf/data/module.f.d.ts +6 -0
- package/bnf/data/module.f.js +57 -4
- package/bnf/data/test.f.d.ts +1 -0
- package/bnf/data/test.f.js +67 -1
- package/ci/module.f.d.ts +3 -0
- package/ci/module.f.js +169 -0
- package/ci/module.js +3 -0
- package/crypto/hmac/module.f.d.ts +5 -4
- package/crypto/hmac/module.f.js +9 -18
- package/crypto/hmac/test.f.d.ts +1 -0
- package/crypto/hmac/test.f.js +16 -8
- package/crypto/secp/module.f.d.ts +14 -11
- package/crypto/secp/module.f.js +33 -13
- package/crypto/secp/test.f.js +12 -13
- package/crypto/sha2/module.f.d.ts +11 -5
- package/crypto/sha2/module.f.js +4 -3
- package/crypto/sha2/test.f.d.ts +4 -1
- package/crypto/sha2/test.f.js +41 -31
- package/crypto/sign/module.f.d.ts +17 -4
- package/crypto/sign/module.f.js +141 -46
- package/crypto/sign/test.f.d.ts +11 -1
- package/crypto/sign/test.f.js +631 -1
- package/dev/tf/all.test.js +9 -1
- package/djs/ast/module.f.d.ts +3 -3
- package/djs/ast/test.f.js +7 -8
- package/djs/parser/module.f.d.ts +3 -3
- package/djs/parser/module.f.js +4 -4
- package/djs/parser/test.f.js +76 -77
- package/djs/serializer/module.f.d.ts +8 -8
- package/djs/serializer/module.f.js +4 -7
- package/djs/serializer/test.f.js +8 -9
- package/djs/tokenizer/module.f.d.ts +2 -2
- package/djs/tokenizer/module.f.js +3 -5
- package/djs/tokenizer/test.f.js +8 -10
- package/djs/transpiler/module.f.d.ts +3 -3
- package/djs/transpiler/module.f.js +2 -0
- package/fsc/bnf.f.d.ts +1 -1
- package/fsc/bnf.f.js +39 -51
- package/fsc/json.f.d.ts +1 -1
- package/fsc/json.f.js +56 -81
- package/fsc/test.f.js +4 -6
- package/fsm/module.f.js +3 -3
- package/fsm/test.f.js +21 -25
- package/html/module.f.js +17 -4
- package/html/test.f.d.ts +7 -0
- package/html/test.f.js +37 -0
- package/issues/031-json.f.d.ts +1 -0
- package/js/tokenizer/module.f.d.ts +4 -4
- package/js/tokenizer/module.f.js +12 -17
- package/js/tokenizer/test.f.js +9 -11
- package/json/module.f.d.ts +6 -6
- package/json/module.f.js +5 -10
- package/json/parser/module.f.d.ts +4 -4
- package/json/parser/module.f.js +7 -4
- package/json/parser/test.f.js +47 -49
- package/json/serializer/module.f.d.ts +6 -6
- package/json/serializer/module.f.js +3 -2
- package/json/serializer/test.f.js +13 -13
- package/json/test.f.js +13 -15
- package/json/tokenizer/module.f.d.ts +4 -4
- package/json/tokenizer/module.f.js +6 -7
- package/json/tokenizer/test.f.js +7 -9
- package/nanvm-lib/tests/vm/test.f.js +1 -1
- package/package.json +5 -5
- package/path/module.f.d.ts +3 -2
- package/text/ascii/test.f.js +2 -2
- package/text/module.f.d.ts +3 -2
- package/text/module.f.js +2 -2
- package/text/test.f.js +3 -3
- package/text/utf16/test.f.js +2 -2
- package/text/utf8/test.f.js +2 -2
- package/types/array/test.f.js +2 -2
- package/types/bigint/module.f.d.ts +6 -3
- package/types/bigint/module.f.js +12 -11
- package/types/bigint/test.f.d.ts +2 -0
- package/types/bigint/test.f.js +21 -2
- package/types/bit_vec/module.f.d.ts +66 -34
- package/types/bit_vec/module.f.js +97 -32
- package/types/bit_vec/test.f.d.ts +7 -0
- package/types/bit_vec/test.f.js +283 -62
- package/types/btree/find/test.f.js +9 -8
- package/types/btree/remove/test.f.js +4 -4
- package/types/btree/set/test.f.js +4 -4
- package/types/btree/test.f.js +7 -7
- package/types/byte_set/test.f.js +2 -2
- package/types/function/compare/module.f.d.ts +15 -1
- package/types/function/compare/module.f.js +1 -1
- package/types/function/compare/test.f.js +37 -4
- package/types/list/test.f.js +93 -93
- package/types/monoid/module.f.d.ts +4 -4
- package/types/monoid/module.f.js +3 -3
- package/types/monoid/test.f.js +3 -3
- package/types/nominal/module.f.d.ts +5 -0
- package/types/nominal/module.f.js +4 -0
- package/types/nominal/test.f.d.ts +5 -0
- package/types/nominal/test.f.js +53 -0
- package/types/number/module.f.js +2 -2
- package/{crypto → types}/prime_field/module.f.d.ts +2 -2
- package/{crypto → types}/prime_field/module.f.js +5 -4
- package/{crypto → types}/prime_field/test.f.js +13 -13
- package/types/range_map/test.f.js +21 -21
- package/types/sorted_list/test.f.js +10 -10
- package/types/sorted_set/test.f.js +14 -14
- package/types/string/module.f.js +2 -2
- package/types/string_set/module.f.js +3 -3
- package/bnf/func/module.f.d.ts +0 -148
- package/bnf/func/module.f.js +0 -132
- package/bnf/func/test.f.d.ts +0 -12
- package/bnf/func/test.f.js +0 -171
- package/bnf/func/testlib.f.d.ts +0 -25
- package/bnf/func/testlib.f.js +0 -150
- /package/{issues/31-json.f.d.ts → ci/module.d.ts} +0 -0
- /package/issues/{31-json.f.js → 031-json.f.js} +0 -0
- /package/{crypto → types}/prime_field/test.f.d.ts +0 -0
package/bnf/data/module.f.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export type Rule = Variant | Sequence | TerminalRange;
|
|
|
11
11
|
/** The full grammar */
|
|
12
12
|
export type RuleSet = Readonly<Record<string, Rule>>;
|
|
13
13
|
type EmptyTag = string | true | undefined;
|
|
14
|
+
type EmptyTagEntry = string | boolean;
|
|
14
15
|
type DispatchRule = {
|
|
15
16
|
readonly emptyTag: EmptyTag;
|
|
16
17
|
readonly rangeMap: Dispatch;
|
|
@@ -25,6 +26,10 @@ type DispatchRuleCollection = {
|
|
|
25
26
|
type DispatchMap = {
|
|
26
27
|
readonly [id in string]: DispatchRule;
|
|
27
28
|
};
|
|
29
|
+
type EmptyTagMap = {
|
|
30
|
+
readonly [id in string]: EmptyTagEntry;
|
|
31
|
+
};
|
|
32
|
+
export type DescentMatchRule = (r: Rule, s: readonly CodePoint[], idx: number) => MatchResult;
|
|
28
33
|
/**
|
|
29
34
|
* Represents a parsed Abstract Syntax Tree (AST) sequence.
|
|
30
35
|
*/
|
|
@@ -52,6 +57,7 @@ export type Match = (name: string, s: readonly CodePoint[]) => MatchResult;
|
|
|
52
57
|
export type MatchRule = (dr: DispatchRule, s: readonly CodePoint[]) => MatchResult;
|
|
53
58
|
export declare const toData: (fr: FRule) => readonly [RuleSet, string];
|
|
54
59
|
export declare const dispatchMap: (ruleSet: RuleSet) => DispatchMap;
|
|
60
|
+
export declare const createEmptyTagMap: (data: readonly [RuleSet, string]) => EmptyTagMap;
|
|
55
61
|
export declare const parser: (fr: FRule) => Match;
|
|
56
62
|
export declare const parserRuleSet: (ruleSet: RuleSet) => Match;
|
|
57
63
|
export {};
|
package/bnf/data/module.f.js
CHANGED
|
@@ -161,6 +161,62 @@ export const dispatchMap = (ruleSet) => {
|
|
|
161
161
|
}
|
|
162
162
|
return result;
|
|
163
163
|
};
|
|
164
|
+
const emptyTagMapAdd = (ruleSet) => (map) => (name) => {
|
|
165
|
+
if (name in map) {
|
|
166
|
+
return [ruleSet, map, map[name]];
|
|
167
|
+
}
|
|
168
|
+
const rule = ruleSet[name];
|
|
169
|
+
if (typeof rule === 'number') {
|
|
170
|
+
return [ruleSet, { ...map, [name]: false }, false];
|
|
171
|
+
}
|
|
172
|
+
else if (rule instanceof Array) {
|
|
173
|
+
map = { ...map, [name]: true };
|
|
174
|
+
let emptyTag = rule.length == 0;
|
|
175
|
+
for (const item of rule) {
|
|
176
|
+
const [, newMap, itemEmptyTag] = emptyTagMapAdd(ruleSet)(map)(item);
|
|
177
|
+
map = newMap;
|
|
178
|
+
if (emptyTag === false) {
|
|
179
|
+
emptyTag = itemEmptyTag !== false;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return [ruleSet, { ...map, [name]: emptyTag }, emptyTag];
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
map = { ...map, [name]: true };
|
|
186
|
+
const entries = Object.entries(rule);
|
|
187
|
+
let emptyTag = false;
|
|
188
|
+
for (const [tag, item] of entries) {
|
|
189
|
+
const [, newMap, itemEmptyTag] = emptyTagMapAdd(ruleSet)(map)(item);
|
|
190
|
+
map = newMap;
|
|
191
|
+
if (itemEmptyTag !== false) {
|
|
192
|
+
emptyTag = tag;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return [ruleSet, { ...map, [name]: emptyTag }, emptyTag];
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
export const createEmptyTagMap = (data) => {
|
|
199
|
+
return emptyTagMapAdd(data[0])({})(data[1])[1];
|
|
200
|
+
};
|
|
201
|
+
// export const parserDescent = (fr: FRule): Match => {
|
|
202
|
+
// const data = toData(fr)
|
|
203
|
+
// const getEmptyTag = (rule: Rule): EmptyTag => {
|
|
204
|
+
// return todo()
|
|
205
|
+
// }
|
|
206
|
+
// const f: DescentMatchRule = (r, cp, idx): MatchResult => {
|
|
207
|
+
// const mrSuccess = (tag: AstTag, sequence: AstSequence, r: Remainder): MatchResult => [{tag, sequence}, true, r]
|
|
208
|
+
// const mrFail = (tag: AstTag, sequence: AstSequence, r: Remainder): MatchResult => [{tag, sequence}, false, r]
|
|
209
|
+
// if (idx >= cp.length) {
|
|
210
|
+
// const emptyTag = getEmptyTag(r)
|
|
211
|
+
// return mrSuccess(emptyTag, [], emptyTag === undefined ? null : cp)
|
|
212
|
+
// }
|
|
213
|
+
// return todo()
|
|
214
|
+
// }
|
|
215
|
+
// const match: Match = (name, cp): MatchResult => {
|
|
216
|
+
// return f(data[0][name], cp, 0)
|
|
217
|
+
// }
|
|
218
|
+
// return match
|
|
219
|
+
// }
|
|
164
220
|
export const parser = (fr) => {
|
|
165
221
|
const data = toData(fr);
|
|
166
222
|
return parserRuleSet(data[0]);
|
|
@@ -202,8 +258,5 @@ export const parserRuleSet = (ruleSet) => {
|
|
|
202
258
|
}
|
|
203
259
|
return mrSuccess(tag, seq, r);
|
|
204
260
|
};
|
|
205
|
-
|
|
206
|
-
return f(map[name], cp);
|
|
207
|
-
};
|
|
208
|
-
return match;
|
|
261
|
+
return (name, cp) => f(map[name], cp);
|
|
209
262
|
};
|
package/bnf/data/test.f.d.ts
CHANGED
package/bnf/data/test.f.js
CHANGED
|
@@ -5,7 +5,7 @@ import { toArray } from "../../types/list/module.f.js";
|
|
|
5
5
|
import { sort } from "../../types/object/module.f.js";
|
|
6
6
|
import { join0Plus, max, option, range, remove, repeat, repeat0Plus, set } from "../module.f.js";
|
|
7
7
|
import { classic, deterministic } from "../testlib.f.js";
|
|
8
|
-
import { dispatchMap, parser, parserRuleSet, toData } from "./module.f.js";
|
|
8
|
+
import { dispatchMap, parser, parserRuleSet, toData, createEmptyTagMap } from "./module.f.js";
|
|
9
9
|
export default {
|
|
10
10
|
toData: [
|
|
11
11
|
() => {
|
|
@@ -87,6 +87,72 @@ export default {
|
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
],
|
|
90
|
+
emptyTags: [
|
|
91
|
+
() => {
|
|
92
|
+
const stringRule = 'true';
|
|
93
|
+
const data = toData(stringRule);
|
|
94
|
+
const emptyTags = createEmptyTagMap(data);
|
|
95
|
+
const result = JSON.stringify(emptyTags);
|
|
96
|
+
if (result !== '{"0":false,"1":false,"2":false,"3":false,"":false}') {
|
|
97
|
+
throw result;
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
() => {
|
|
101
|
+
const terminalRangeRule = range('AF');
|
|
102
|
+
const data = toData(terminalRangeRule);
|
|
103
|
+
const emptyTags = createEmptyTagMap(data);
|
|
104
|
+
const result = JSON.stringify(emptyTags);
|
|
105
|
+
if (result !== '{"":false}') {
|
|
106
|
+
throw result;
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
() => {
|
|
110
|
+
const varintRule = { true: 'true', false: 'false' };
|
|
111
|
+
const data = toData(varintRule);
|
|
112
|
+
const emptyTags = createEmptyTagMap(data);
|
|
113
|
+
const result = JSON.stringify(emptyTags);
|
|
114
|
+
if (result !== '{"0":false,"1":false,"2":false,"3":false,"4":false,"5":false,"6":false,"7":false,"8":false,"9":false,"":false}') {
|
|
115
|
+
throw result;
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
() => {
|
|
119
|
+
const emptyRule = '';
|
|
120
|
+
const data = toData(emptyRule);
|
|
121
|
+
const emptyTags = createEmptyTagMap(data);
|
|
122
|
+
const result = JSON.stringify(emptyTags);
|
|
123
|
+
if (result !== '{"":true}') {
|
|
124
|
+
throw result;
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
() => {
|
|
128
|
+
const emptyRule = '';
|
|
129
|
+
const varintRule = { true: 'true', e: emptyRule };
|
|
130
|
+
const data = toData(varintRule);
|
|
131
|
+
const emptyTags = createEmptyTagMap(data);
|
|
132
|
+
const result = JSON.stringify(emptyTags);
|
|
133
|
+
if (result !== '{"0":false,"1":false,"2":false,"3":false,"4":false,"5":true,"":"e"}') {
|
|
134
|
+
throw result;
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
() => {
|
|
138
|
+
const repeatRule = repeat0Plus(option('a'));
|
|
139
|
+
const data = toData(repeatRule);
|
|
140
|
+
const emptyTags = createEmptyTagMap(data);
|
|
141
|
+
const result = JSON.stringify(emptyTags);
|
|
142
|
+
if (result !== '{"0":"none","1":false,"2":false,"3":true,"r":"none","":true}') {
|
|
143
|
+
throw result;
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
() => {
|
|
147
|
+
const repeatRule = repeat0Plus(set(' \n\r\t'));
|
|
148
|
+
const data = toData(repeatRule);
|
|
149
|
+
const emptyTags = createEmptyTagMap(data);
|
|
150
|
+
const result = JSON.stringify(emptyTags);
|
|
151
|
+
if (result !== '{"0":false,"1":false,"2":false,"3":false,"4":false,"5":true,"r":"none","":true}') {
|
|
152
|
+
throw result;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
],
|
|
90
156
|
variantTest: () => {
|
|
91
157
|
const varintRule = { a: 'a', b: 'b' };
|
|
92
158
|
const result = stringify(sort)(toData(varintRule));
|
package/ci/module.f.d.ts
ADDED
package/ci/module.f.js
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
const os = ['ubuntu', 'macos', 'windows'];
|
|
2
|
+
const architecture = ['intel', 'arm'];
|
|
3
|
+
// https://docs.github.com/en/actions/reference/runners/github-hosted-runners#standard-github-hosted-runners-for-public-repositories
|
|
4
|
+
const images = {
|
|
5
|
+
ubuntu: {
|
|
6
|
+
intel: 'ubuntu-latest',
|
|
7
|
+
arm: 'ubuntu-24.04-arm'
|
|
8
|
+
},
|
|
9
|
+
macos: {
|
|
10
|
+
intel: 'macos-15-intel',
|
|
11
|
+
arm: 'macos-latest'
|
|
12
|
+
},
|
|
13
|
+
windows: {
|
|
14
|
+
intel: 'windows-latest',
|
|
15
|
+
arm: 'windows-11-arm',
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const install = (step) => ({ type: 'install', step });
|
|
19
|
+
const test = (step) => ({ type: 'test', step });
|
|
20
|
+
const installOnWindowsArm = ({ def, name, path }) => (v) => (a) => install(v === 'windows' && a === 'arm'
|
|
21
|
+
? { run: `irm ${path}/install.ps1 | iex; "$env:USERPROFILE\\.${name}\\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append` }
|
|
22
|
+
: def);
|
|
23
|
+
const installBun = installOnWindowsArm({
|
|
24
|
+
def: { uses: 'oven-sh/setup-bun@v1' },
|
|
25
|
+
name: 'bun',
|
|
26
|
+
path: 'bun.sh'
|
|
27
|
+
});
|
|
28
|
+
const installDeno = installOnWindowsArm({
|
|
29
|
+
def: { uses: 'denoland/setup-deno@v2', with: { 'deno-version': '2' } },
|
|
30
|
+
name: 'deno',
|
|
31
|
+
path: 'deno.land'
|
|
32
|
+
});
|
|
33
|
+
const cargoTest = (target, config) => {
|
|
34
|
+
const to = target ? ` --target ${target}` : '';
|
|
35
|
+
const co = config ? ` --config ${config}` : '';
|
|
36
|
+
const main = `cargo test${to}${co}`;
|
|
37
|
+
return [
|
|
38
|
+
test({ run: main }),
|
|
39
|
+
test({ run: `${main} --release` })
|
|
40
|
+
];
|
|
41
|
+
};
|
|
42
|
+
const customTarget = (target) => [
|
|
43
|
+
{ type: 'rust', target },
|
|
44
|
+
...cargoTest(target)
|
|
45
|
+
];
|
|
46
|
+
const wasmTarget = (target) => [
|
|
47
|
+
...customTarget(target),
|
|
48
|
+
...cargoTest(target, '.cargo/config.wasmer.toml')
|
|
49
|
+
];
|
|
50
|
+
const clean = (steps) => [
|
|
51
|
+
...steps,
|
|
52
|
+
test({ run: 'git reset --hard HEAD && git clean -fdx' })
|
|
53
|
+
];
|
|
54
|
+
const installNode = (version) => ({ uses: 'actions/setup-node@v6', with: { 'node-version': version } });
|
|
55
|
+
const basicNode = (version) => (extra) => clean([
|
|
56
|
+
install(installNode(version)),
|
|
57
|
+
test({ run: 'npm ci' }),
|
|
58
|
+
...extra,
|
|
59
|
+
]);
|
|
60
|
+
const node = (version) => (extra) => basicNode(version)([
|
|
61
|
+
test({ run: 'npm test' }),
|
|
62
|
+
test({ run: 'npm run fst' }),
|
|
63
|
+
...extra,
|
|
64
|
+
]);
|
|
65
|
+
const findTgz = (v) => v === 'windows' ? '(Get-ChildItem *.tgz).FullName' : './*.tgz';
|
|
66
|
+
const toSteps = (m) => {
|
|
67
|
+
const filter = (st) => m.flatMap((mt) => mt.type === st ? [mt.step] : []);
|
|
68
|
+
const aptGet = m.flatMap(v => v.type === 'apt-get' ? [v.package] : []).join(' ');
|
|
69
|
+
const rust = m.find(v => v.type === 'rust') !== undefined;
|
|
70
|
+
const targets = m.flatMap(v => v.type === 'rust' && v.target !== undefined ? [v.target] : []).join(',');
|
|
71
|
+
return [
|
|
72
|
+
...(aptGet !== '' ? [{ run: `sudo apt-get update && sudo apt-get install -y ${aptGet}` }] : []),
|
|
73
|
+
...(rust ? [{
|
|
74
|
+
// wasm32-wasip1-threads doesn't work on Rust 1.91 in the release mode.
|
|
75
|
+
// See https://github.com/sergey-shandar/wasmtime-crash
|
|
76
|
+
uses: 'dtolnay/rust-toolchain@1.90.0',
|
|
77
|
+
with: {
|
|
78
|
+
components: 'rustfmt,clippy',
|
|
79
|
+
targets
|
|
80
|
+
}
|
|
81
|
+
}] : []),
|
|
82
|
+
...filter('install'),
|
|
83
|
+
{ uses: 'actions/checkout@v5' },
|
|
84
|
+
...filter('test'),
|
|
85
|
+
];
|
|
86
|
+
};
|
|
87
|
+
const nodes = ['20', '22', '25'];
|
|
88
|
+
const nodeTest = (v) => v === '20' ? 'run test20' : 'test';
|
|
89
|
+
const nodeSteps = (v) => [
|
|
90
|
+
install(installNode(v)),
|
|
91
|
+
test({ run: 'npm ci' }),
|
|
92
|
+
test({ run: `npm ${nodeTest(v)}` }),
|
|
93
|
+
];
|
|
94
|
+
const ubuntu = (ms) => ({
|
|
95
|
+
'runs-on': 'ubuntu-latest',
|
|
96
|
+
steps: toSteps(ms)
|
|
97
|
+
});
|
|
98
|
+
const nodeVersions = Object.fromEntries(nodes.map(v => [`node${v}`, ubuntu(nodeSteps(v))]));
|
|
99
|
+
const steps = (v) => (a) => {
|
|
100
|
+
const result = [
|
|
101
|
+
// Rust
|
|
102
|
+
test({ run: 'cargo fmt -- --check' }),
|
|
103
|
+
test({ run: 'cargo clippy -- -D warnings' }),
|
|
104
|
+
...cargoTest(),
|
|
105
|
+
install({ uses: 'bytecodealliance/actions/wasmtime/setup@v1' }),
|
|
106
|
+
install({ uses: 'wasmerio/setup-wasmer@v1' }),
|
|
107
|
+
...wasmTarget('wasm32-wasip1'),
|
|
108
|
+
...wasmTarget('wasm32-wasip2'),
|
|
109
|
+
...wasmTarget('wasm32-unknown-unknown'),
|
|
110
|
+
...wasmTarget('wasm32-wasip1-threads'),
|
|
111
|
+
...(a !== 'intel' ? [] :
|
|
112
|
+
v === 'windows' ?
|
|
113
|
+
customTarget('i686-pc-windows-msvc') :
|
|
114
|
+
v === 'ubuntu' ? [
|
|
115
|
+
{ type: 'apt-get', package: 'libc6-dev-i386' },
|
|
116
|
+
...customTarget('i686-unknown-linux-gnu'),
|
|
117
|
+
] :
|
|
118
|
+
[]),
|
|
119
|
+
// Node.js
|
|
120
|
+
...node('24')([
|
|
121
|
+
// TypeScript Preview
|
|
122
|
+
install({ run: 'npm install -g @typescript/native-preview' }),
|
|
123
|
+
test({ run: 'tsgo' }),
|
|
124
|
+
// Playwright
|
|
125
|
+
install({ run: 'npm install -g playwright' }),
|
|
126
|
+
install({ run: 'playwright install --with-deps' }),
|
|
127
|
+
...['chromium', 'firefox', 'webkit'].map(browser => (test({ run: `npx playwright test --browser=${browser}` }))),
|
|
128
|
+
// publishing
|
|
129
|
+
test({ run: 'npm pack' }),
|
|
130
|
+
test({ run: `npm install -g ${findTgz(v)}` }),
|
|
131
|
+
test({ run: 'fsc issues/demo/data/tree.json _tree.f.js' }),
|
|
132
|
+
test({ run: 'fst' }),
|
|
133
|
+
test({ run: 'npm uninstall functionalscript -g' }),
|
|
134
|
+
]),
|
|
135
|
+
// Deno
|
|
136
|
+
...clean([
|
|
137
|
+
installDeno(v)(a),
|
|
138
|
+
test({ run: 'deno install' }),
|
|
139
|
+
test({ run: 'deno task test' }),
|
|
140
|
+
test({ run: 'deno task fst' }),
|
|
141
|
+
test({ run: 'deno publish --dry-run' }),
|
|
142
|
+
]),
|
|
143
|
+
// Bun
|
|
144
|
+
...clean([
|
|
145
|
+
installBun(v)(a),
|
|
146
|
+
test({ run: 'bun test --timeout 20000' }),
|
|
147
|
+
test({ run: 'bun ./dev/tf/module.ts' }),
|
|
148
|
+
]),
|
|
149
|
+
];
|
|
150
|
+
return toSteps(result);
|
|
151
|
+
};
|
|
152
|
+
const jobs = {
|
|
153
|
+
...Object.fromEntries([
|
|
154
|
+
...os.flatMap(v => architecture.map(a => [`${v}-${a}`, {
|
|
155
|
+
'runs-on': images[v][a],
|
|
156
|
+
steps: steps(v)(a),
|
|
157
|
+
}]))
|
|
158
|
+
]),
|
|
159
|
+
...nodeVersions,
|
|
160
|
+
};
|
|
161
|
+
const gha = {
|
|
162
|
+
name: 'CI',
|
|
163
|
+
on: { pull_request: {} },
|
|
164
|
+
jobs,
|
|
165
|
+
};
|
|
166
|
+
export default async (io) => {
|
|
167
|
+
io.fs.writeFileSync('.github/workflows/ci.yml', JSON.stringify(gha, null, ' '));
|
|
168
|
+
return 0;
|
|
169
|
+
};
|
package/ci/module.js
ADDED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Provides an implementation of HMAC (Hash-based Message Authentication Code).
|
|
3
3
|
*
|
|
4
4
|
* https://en.wikipedia.org/wiki/HMAC
|
|
5
|
+
* https://www.rfc-editor.org/rfc/rfc2104
|
|
5
6
|
*
|
|
6
7
|
* @module
|
|
7
8
|
*
|
|
@@ -16,13 +17,13 @@
|
|
|
16
17
|
* if (r !== vec(256n)(0xf7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8n)) { throw r }
|
|
17
18
|
* ```
|
|
18
19
|
*/
|
|
19
|
-
import { type
|
|
20
|
+
import { type Reduce } from '../../types/bit_vec/module.f.ts';
|
|
20
21
|
import { type Sha2 } from '../sha2/module.f.ts';
|
|
21
22
|
/**
|
|
22
|
-
* Generates an HMAC (Hash-based Message Authentication Code) using the specified
|
|
23
|
+
* Generates an HMAC (Hash-based Message Authentication Code) using the specified hash function.
|
|
23
24
|
*
|
|
24
|
-
* @param
|
|
25
|
+
* @param hashFunc - The hash function implementation to use.
|
|
25
26
|
* @returns - A function that takes a key and returns another function
|
|
26
27
|
* that takes a message and computes the HMAC.
|
|
27
28
|
*/
|
|
28
|
-
export declare const hmac: (
|
|
29
|
+
export declare const hmac: (hashFunc: Sha2) => Reduce;
|
package/crypto/hmac/module.f.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Provides an implementation of HMAC (Hash-based Message Authentication Code).
|
|
3
3
|
*
|
|
4
4
|
* https://en.wikipedia.org/wiki/HMAC
|
|
5
|
+
* https://www.rfc-editor.org/rfc/rfc2104
|
|
5
6
|
*
|
|
6
7
|
* @module
|
|
7
8
|
*
|
|
@@ -16,12 +17,9 @@
|
|
|
16
17
|
* if (r !== vec(256n)(0xf7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8n)) { throw r }
|
|
17
18
|
* ```
|
|
18
19
|
*/
|
|
19
|
-
import { length } from "../../types/bit_vec/module.f.js";
|
|
20
|
-
import { empty, msb, vec, vec8 } from "../../types/bit_vec/module.f.js";
|
|
21
|
-
import { flip } from "../../types/function/module.f.js";
|
|
22
|
-
import { repeat } from "../../types/monoid/module.f.js";
|
|
20
|
+
import { length, msb, vec, vec8, repeat } from "../../types/bit_vec/module.f.js";
|
|
23
21
|
import { computeSync } from "../sha2/module.f.js";
|
|
24
|
-
const { concat } = msb;
|
|
22
|
+
const { concat, xor } = msb;
|
|
25
23
|
/**
|
|
26
24
|
* Outer padding.
|
|
27
25
|
*/
|
|
@@ -31,25 +29,18 @@ const oPad = vec8(0x5cn);
|
|
|
31
29
|
*/
|
|
32
30
|
const iPad = vec8(0x36n);
|
|
33
31
|
/**
|
|
34
|
-
*
|
|
35
|
-
*/
|
|
36
|
-
const padRepeat = repeat({ identity: empty, operation: concat });
|
|
37
|
-
/**
|
|
38
|
-
* Generates an HMAC (Hash-based Message Authentication Code) using the specified SHA-2 hash function.
|
|
32
|
+
* Generates an HMAC (Hash-based Message Authentication Code) using the specified hash function.
|
|
39
33
|
*
|
|
40
|
-
* @param
|
|
34
|
+
* @param hashFunc - The hash function implementation to use.
|
|
41
35
|
* @returns - A function that takes a key and returns another function
|
|
42
36
|
* that takes a message and computes the HMAC.
|
|
43
37
|
*/
|
|
44
|
-
export const hmac = (
|
|
45
|
-
const { blockLength } =
|
|
46
|
-
const p =
|
|
38
|
+
export const hmac = (hashFunc) => {
|
|
39
|
+
const { blockLength } = hashFunc;
|
|
40
|
+
const p = repeat(blockLength >> 3n);
|
|
47
41
|
const ip = p(iPad);
|
|
48
42
|
const op = p(oPad);
|
|
49
|
-
const c = computeSync(
|
|
50
|
-
const vbl = vec(blockLength);
|
|
51
|
-
// a and b should have the same size
|
|
52
|
-
const xor = (a) => (b) => vbl(a ^ b);
|
|
43
|
+
const c = computeSync(hashFunc);
|
|
53
44
|
return k => {
|
|
54
45
|
const k1 = length(k) > blockLength ? c([k]) : k;
|
|
55
46
|
const k2 = concat(k1)(vec(blockLength - length(k1))(0n));
|
package/crypto/hmac/test.f.d.ts
CHANGED
package/crypto/hmac/test.f.js
CHANGED
|
@@ -1,23 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { vec } from "../../types/bit_vec/module.f.js";
|
|
3
|
-
import { sha256, sha512 } from "../sha2/module.f.js";
|
|
1
|
+
import { utf8 } from "../../text/module.f.js";
|
|
2
|
+
import { length, uint, vec } from "../../types/bit_vec/module.f.js";
|
|
3
|
+
import { sha256, sha384, sha512 } from "../sha2/module.f.js";
|
|
4
4
|
import { hmac } from "./module.f.js";
|
|
5
5
|
export default {
|
|
6
6
|
example: () => {
|
|
7
|
-
const r = hmac(sha256)(
|
|
7
|
+
const r = hmac(sha256)(utf8('key'))(utf8('The quick brown fox jumps over the lazy dog'));
|
|
8
8
|
if (r !== vec(256n)(0xf7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8n)) {
|
|
9
9
|
throw r;
|
|
10
10
|
}
|
|
11
11
|
},
|
|
12
12
|
sha256: () => {
|
|
13
|
-
const r = hmac(sha256)(
|
|
14
|
-
if (r !==
|
|
13
|
+
const r = hmac(sha256)(utf8('key'))(utf8('The quick brown fox jumps over the lazy dog'));
|
|
14
|
+
if (uint(r) !== 0xf7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8n) {
|
|
15
15
|
throw r;
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
|
+
sha384: () => {
|
|
19
|
+
const k = vec(384n)(0n);
|
|
20
|
+
const m = vec(904n)(0x0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010069c7548c21d0dfea6b9a51c9ead4e27c33d3b3f180316e5bcab92c933f0e4dbc9a9083505bc92276aec4be312696ef7bf3bf603f4bbd381196a029f340585312n);
|
|
21
|
+
const r = hmac(sha384)(k)(m);
|
|
22
|
+
if (r !== vec(384n)(0x8f858157ce005cd52fd8e8f1a46b55e6cfae21c8c183d9c2f7504bedf450609edd7d3c6171dc0bdd2d2444faa28f18ban)) {
|
|
23
|
+
throw uint(r).toString(16);
|
|
24
|
+
}
|
|
25
|
+
},
|
|
18
26
|
sha512: () => {
|
|
19
|
-
const r = hmac(sha512)(
|
|
20
|
-
if (r !==
|
|
27
|
+
const r = hmac(sha512)(utf8('key'))(utf8('The quick brown fox jumps over the lazy dog'));
|
|
28
|
+
if (r !== vec(512n)(0xb42af09057bac1e2d41708e48a902e09b5ff7f12ab428a4fe86653c73dd248fb82f948a549f7b791a5b41915ee4d1ec3935357e4e2317250d0372afa2ebeeb3an)) {
|
|
21
29
|
throw r;
|
|
22
30
|
}
|
|
23
31
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Reduce } from '../../types/function/operator/module.f.ts';
|
|
2
|
-
import { type PrimeField } from '
|
|
1
|
+
import type { Equal, Fold, Reduce } from '../../types/function/operator/module.f.ts';
|
|
2
|
+
import { type PrimeField } from '../../types/prime_field/module.f.ts';
|
|
3
3
|
/**
|
|
4
4
|
* A 2D point represented as a pair of `bigint` values `[x, y]`.
|
|
5
5
|
*/
|
|
@@ -21,14 +21,15 @@ export type Init = {
|
|
|
21
21
|
/**
|
|
22
22
|
* Represents an elliptic curve and its associated operations.
|
|
23
23
|
*/
|
|
24
|
-
type Curve = {
|
|
24
|
+
export type Curve = {
|
|
25
25
|
readonly pf: PrimeField;
|
|
26
26
|
readonly nf: PrimeField;
|
|
27
|
+
readonly g: Point;
|
|
27
28
|
readonly y2: (x: bigint) => bigint;
|
|
28
29
|
readonly y: (x: bigint) => bigint | null;
|
|
29
30
|
readonly neg: (a: Point) => Point;
|
|
30
31
|
readonly add: Reduce<Point>;
|
|
31
|
-
readonly mul:
|
|
32
|
+
readonly mul: Fold<bigint, Point>;
|
|
32
33
|
};
|
|
33
34
|
/**
|
|
34
35
|
* Constructs an elliptic curve with the given initialization parameters.
|
|
@@ -50,27 +51,29 @@ type Curve = {
|
|
|
50
51
|
* const mulPoint = curveInstance.mul([1n, 1n])(3n); // Multiply a point by 3
|
|
51
52
|
* ```
|
|
52
53
|
*/
|
|
53
|
-
export declare const curve: ({ p, a: [a0, a1], n }: Init) => Curve;
|
|
54
|
-
export declare const eq:
|
|
54
|
+
export declare const curve: ({ p, a: [a0, a1], n, g }: Init) => Curve;
|
|
55
|
+
export declare const eq: Equal<Point>;
|
|
55
56
|
/**
|
|
56
57
|
* https://neuromancer.sk/std/secg/secp192r1
|
|
58
|
+
* NIST P-192
|
|
57
59
|
*/
|
|
58
|
-
export declare const secp192r1:
|
|
60
|
+
export declare const secp192r1: Curve;
|
|
59
61
|
/**
|
|
60
62
|
* https://en.bitcoin.it/wiki/Secp256k1
|
|
61
63
|
* https://neuromancer.sk/std/secg/secp256k1
|
|
62
64
|
*/
|
|
63
|
-
export declare const secp256k1:
|
|
65
|
+
export declare const secp256k1: Curve;
|
|
64
66
|
/**
|
|
65
67
|
* https://neuromancer.sk/std/secg/secp256r1
|
|
68
|
+
* NIST P-256
|
|
66
69
|
*/
|
|
67
|
-
export declare const secp256r1:
|
|
70
|
+
export declare const secp256r1: Curve;
|
|
68
71
|
/**
|
|
69
72
|
* https://neuromancer.sk/std/secg/secp384r1
|
|
70
73
|
*/
|
|
71
|
-
export declare const secp384r1:
|
|
74
|
+
export declare const secp384r1: Curve;
|
|
72
75
|
/**
|
|
73
76
|
* https://neuromancer.sk/std/secg/secp521r1
|
|
74
77
|
*/
|
|
75
|
-
export declare const secp521r1:
|
|
78
|
+
export declare const secp521r1: Curve;
|
|
76
79
|
export {};
|