@amritk/nish-x86_64-linux 0.16.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/INSTALL.md +43 -34
  2. package/bin/nish +0 -0
  3. package/package.json +1 -1
  4. package/runtime/nish.d.ts +117 -8
  5. package/runtime/nish.h +50 -13
  6. package/runtime/nish.mjs +71 -7
  7. package/runtime/runtime-host.c +43 -24
  8. package/runtime/runtime-net.c +57 -10
  9. package/runtime/runtime-os.c +62 -20
  10. package/runtime/runtime-simd.c +203 -0
  11. package/runtime/runtime-wasm.c +12 -0
  12. package/runtime/runtime.c +66 -18
  13. package/runtime/shim.mjs +114 -5
  14. package/scripts/build.sh +14 -12
  15. package/std/README.md +168 -36
  16. package/std/crypto/aes.ts +51 -8
  17. package/std/crypto/base64url.ts +25 -12
  18. package/std/crypto/chacha20poly1305.ts +43 -29
  19. package/std/crypto/ct.ts +6 -1
  20. package/std/crypto/hkdf.ts +364 -3
  21. package/std/crypto/hmac.ts +307 -7
  22. package/std/crypto/p256.ts +618 -34
  23. package/std/crypto/sha1.ts +147 -0
  24. package/std/crypto/sha256.ts +3 -2
  25. package/std/crypto/x25519.ts +88 -36
  26. package/std/crypto/x509.ts +130 -47
  27. package/std/json.ts +297 -41
  28. package/std/net/hpack.ts +1094 -0
  29. package/std/net/http-fields.ts +604 -0
  30. package/std/net/http1-server.ts +1389 -0
  31. package/std/net/http1.ts +1492 -0
  32. package/std/net/http2-frame.ts +745 -0
  33. package/std/net/http2-tls.ts +216 -0
  34. package/std/net/http2.ts +1433 -0
  35. package/std/net/http3-frame.ts +457 -0
  36. package/std/net/http3-server.ts +911 -0
  37. package/std/net/http3.ts +2145 -0
  38. package/std/net/qpack.ts +1163 -0
  39. package/std/net/quic-conn-ack.ts +206 -0
  40. package/std/net/quic-conn-cid.ts +425 -0
  41. package/std/net/quic-conn-params.ts +462 -0
  42. package/std/net/quic-datagram.ts +130 -0
  43. package/std/net/quic-frame.ts +1206 -0
  44. package/std/net/quic-listener.ts +929 -0
  45. package/std/net/quic-packet.ts +1698 -0
  46. package/std/net/quic-recovery.ts +849 -0
  47. package/std/net/quic-stream.ts +1609 -0
  48. package/std/net/quic.ts +3578 -0
  49. package/std/net/tls/codec.ts +1089 -0
  50. package/std/net/tls/record-server.ts +1173 -0
  51. package/std/net/tls/record.ts +621 -0
  52. package/std/net/tls/schedule.ts +429 -0
  53. package/std/net/tls-tcp.ts +414 -0
  54. package/std/net/tls.ts +1437 -0
  55. package/std/net/websocket.ts +823 -0
  56. package/std/net/webtransport.ts +1334 -0
  57. package/std/secret.ts +62 -0
  58. package/std/text.ts +77 -0
package/std/secret.ts ADDED
@@ -0,0 +1,62 @@
1
+ /**
2
+ * `nish:secret` — key material, and the rules that keep it in
3
+ * (docs/LANGUAGE.md, "Secrets").
4
+ *
5
+ * import { Secret, expose, secret, wipe } from "nish:secret"
6
+ *
7
+ * const key: Secret<u8[]> = secret(readKey())
8
+ * const tag: u8[] = expose(key, (k: u8[]): u8[] => hmacSha256(k, message))
9
+ * wipe(key)
10
+ *
11
+ * This file is the source behind the builtin module, and it is imported only
12
+ * by that name: `nish/secret` is refused, so there is one spelling for the
13
+ * checker's rules to be read under. What is written here is the meaning; what
14
+ * makes a `Secret` worth having is in `src/secret.ts`, which knows this module
15
+ * by its path and package:
16
+ *
17
+ * - a `Secret` is opaque. Nothing outside this file reads its field, builds
18
+ * one with `new`, prints it, interpolates it, compares it with anything but
19
+ * another `Secret` or `null`, branches on it, indexes it, stores it in a
20
+ * field, an array or a `Result`, or hands it to a builtin;
21
+ * - a `Secret` a function makes leaves it returned or wiped, on every path;
22
+ * - `expose` is the one way in, and the function it runs may reach no I/O and
23
+ * no C, may not keep the value, may not write the argument `exposeWith`
24
+ * hands it, and returns a declared type that holds no `Secret`;
25
+ * - `wipe` is a volatile store of zeros over the value's whole storage,
26
+ * which no optimiser may remove (`src/emit-secret.ts`).
27
+ *
28
+ * Under Node the module is answered by `runtime/shim.mjs`, where a `Secret` is
29
+ * a plain wrapper and `wipe` zero-fills it.
30
+ */
31
+
32
+ /**
33
+ * Key material: an array of integers (`u8[]`, `u32[]`, ...) or a record whose
34
+ * every field is an integer. Made by `secret`, read only through `expose`.
35
+ */
36
+ export class Secret<T> {
37
+ /** The wrapped value. Only this module reads or writes it (`src/secret.ts`). */
38
+ value: T
39
+
40
+ constructor(value: T) {
41
+ this.value = value
42
+ }
43
+ }
44
+
45
+ /** `value`, wrapped. The argument is moved: a local handed in is not read again. */
46
+ export const secret = <T>(value: T): Secret<T> => new Secret<T>(value)
47
+
48
+ /** `f(value)`: the one way to compute with what a `Secret` holds. */
49
+ export const expose = <T, R>(s: Secret<T>, f: (value: T) => R): R => f(s.value)
50
+
51
+ /** `f(value, arg)`: `expose` with one more argument, because an arrow captures nothing. */
52
+ export const exposeWith = <T, A, R>(s: Secret<T>, arg: A, f: (value: T, arg: A) => R): R => f(s.value, arg)
53
+
54
+ /**
55
+ * Zero every byte of `target`'s storage: a `Secret`'s value, or an array or
56
+ * record of integers that `expose`'s function holds. Natively the compiler
57
+ * gives each instance a body of its own, one volatile `llvm.memset`
58
+ * (`src/emit-secret.ts`); this one is never emitted.
59
+ */
60
+ export const wipe = <T>(_target: T): void => {
61
+ // Lowered by the compiler: see above.
62
+ }
package/std/text.ts CHANGED
@@ -191,3 +191,80 @@ export const firstDifference = (left: string[], right: string[]): i32 => {
191
191
  }
192
192
  return leftLength === rightLength ? -1 : i
193
193
  }
194
+
195
+ /** The most bytes `indexOfAny` takes in its set: what one 16-byte vector of the runtime kernel compares. */
196
+ const INDEX_OF_ANY_MAX_SET: i32 = 16
197
+
198
+ /** The first byte that is not ASCII; `indexOfAny`'s set must stay below it. */
199
+ const NON_ASCII: i32 = 128
200
+
201
+ /**
202
+ * The first index at or after `from` whose byte is one of `bytes`, or -1.
203
+ *
204
+ * `bytes` is a set of 1 to 16 ASCII bytes, and anything else panics: an empty
205
+ * set matches nothing, more than 16 is more than one vector of the runtime
206
+ * kernel compares, and an ASCII set is what keeps the answer the same under Node,
207
+ * where `charCodeAt` reads a UTF-16 unit rather than a byte. An ASCII byte
208
+ * never occurs inside a multi-byte UTF-8 sequence, so a non-ASCII `text`
209
+ * passes through and only its ASCII bytes can match — as in `splitLines`, the
210
+ * index is a byte offset natively. `from` is clamped to `[0, text.length]`,
211
+ * as `substring` clamps, so a negative `from` searches from the start and one
212
+ * past the end answers -1.
213
+ *
214
+ * Natively the search is the runtime's `nish_str_index_of_any`, which reads
215
+ * 16 or 32 bytes at a time (docs/LANGUAGE.md, "Byte search"). It is
216
+ * **variable-time**: how long it takes says where the first match is, so it is
217
+ * never for secret data.
218
+ */
219
+ export const indexOfAny = (text: string, bytes: string, from: i32): i32 => {
220
+ const count: i32 = toI32(bytes.length)
221
+ if (count < 1 || count > INDEX_OF_ANY_MAX_SET) {
222
+ panic("indexOfAny: the set must hold 1 to 16 bytes")
223
+ }
224
+ let j: i32 = 0
225
+ while (j < count) {
226
+ if (toI32(bytes.charCodeAt(j)) >= NON_ASCII) {
227
+ panic("indexOfAny: every byte of the set must be ASCII")
228
+ }
229
+ j += 1
230
+ }
231
+ const length: i32 = toI32(text.length)
232
+ let start: i32 = from
233
+ if (start < 0) {
234
+ start = 0
235
+ }
236
+ if (start > length) {
237
+ start = length
238
+ }
239
+ return indexOfAnyFrom(text, bytes, start)
240
+ }
241
+
242
+ /**
243
+ * `indexOfAny`'s walk, once its arguments are checked: the first index at or
244
+ * after `from` whose byte is in `bytes`, or -1.
245
+ *
246
+ * This loop is what runs under Node. Natively the compiler recognises the one
247
+ * call `indexOfAny` makes to it and calls the runtime kernel instead
248
+ * (`src/kernels.ts`), so the loop is the kernel's meaning written in the
249
+ * language rather than its implementation. The name is long for the reason
250
+ * `isTextBlankByte`'s is.
251
+ */
252
+ const indexOfAnyFrom = (text: string, bytes: string, from: i32): i32 => {
253
+ const length: i32 = toI32(text.length)
254
+ const count: i32 = toI32(bytes.length)
255
+ let i: i32 = from
256
+ // `from` is never negative, because `indexOfAny` clamped it; the test is
257
+ // written because it is what proves `i` within `text`, as in `splitLines`.
258
+ while (i >= 0 && i < length) {
259
+ const code: i32 = toI32(text.charCodeAt(i))
260
+ let j: i32 = 0
261
+ while (j < count) {
262
+ if (toI32(bytes.charCodeAt(j)) === code) {
263
+ return i
264
+ }
265
+ j += 1
266
+ }
267
+ i += 1
268
+ }
269
+ return -1
270
+ }