@amritk/nish-x86_64-linux 0.24.0 → 0.25.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 (42) hide show
  1. package/bin/nish +0 -0
  2. package/docs/AI.md +24 -4
  3. package/package.json +1 -1
  4. package/runtime/browser.mjs +4 -3
  5. package/runtime/core/host.d.ts +8 -0
  6. package/runtime/core/host.mjs +50 -2
  7. package/runtime/nish.d.ts +100 -0
  8. package/runtime/nish.h +34 -0
  9. package/runtime/nish.mjs +21 -0
  10. package/runtime/node.mjs +57 -6
  11. package/runtime/runtime-net.c +44 -3
  12. package/runtime/runtime-os.c +115 -12
  13. package/scripts/build.sh +13 -3
  14. package/std/README.md +25 -8
  15. package/std/cli-args.ts +1216 -0
  16. package/std/cli-flags.ts +585 -0
  17. package/std/cli.ts +308 -19
  18. package/std/compress/checksum.ts +132 -20
  19. package/std/compress/deflate.ts +638 -248
  20. package/std/compress/gzip.ts +20 -6
  21. package/std/crypto/LICENSE-fiat-crypto-p384 +21 -0
  22. package/std/crypto/p256.ts +63 -1
  23. package/std/crypto/p384.ts +6044 -0
  24. package/std/crypto/pki-roots.ts +322 -0
  25. package/std/crypto/pki.ts +1207 -0
  26. package/std/crypto/rsa.ts +663 -0
  27. package/std/crypto/x509.ts +1054 -58
  28. package/std/net/dns-config.ts +734 -0
  29. package/std/net/dns-message.ts +517 -0
  30. package/std/net/dns-resolver.ts +1015 -0
  31. package/std/net/dns.ts +478 -0
  32. package/std/net/http1-client.ts +1227 -0
  33. package/std/net/http1-server.ts +7 -2
  34. package/std/net/http1.ts +9 -9
  35. package/std/net/tls/client.ts +1094 -0
  36. package/std/net/tls/codec.ts +585 -3
  37. package/std/net/tls/record-client.ts +1192 -0
  38. package/std/net/tls/verify.ts +221 -0
  39. package/std/net/tls-tcp.ts +642 -11
  40. package/std/net/tls.ts +2 -2
  41. package/std/net/url.ts +559 -4
  42. package/std/yaml-write.ts +415 -0
@@ -0,0 +1,415 @@
1
+ /**
2
+ * `nish/yaml-write` — a JSON value written as YAML text that `parseYaml` reads
3
+ * back as the same tree.
4
+ *
5
+ * import { JsonDocument } from "nish/json-value"
6
+ * import { JsonLimits } from "nish/json-tokenizer"
7
+ * import { stringifyYaml } from "nish/yaml-write"
8
+ *
9
+ * const doc = new JsonDocument(new JsonLimits())
10
+ * const root = doc.parseText('{"name":"tea","on":"yes","ports":[80,443],"tags":{}}')
11
+ * stringifyYaml(doc, root)
12
+ * // name: tea
13
+ * // "on": "yes"
14
+ * // ports:
15
+ * // - 80
16
+ * // - 443
17
+ * // tags: {}
18
+ *
19
+ * **Block style.** An object is a block map and an array a block sequence,
20
+ * indented two spaces a level, members in their order; an empty one is `{}` or
21
+ * `[]`. A sequence item that is itself a collection starts on the item's line
22
+ * (`- a: 1`). `null`, `true` and `false` are written as themselves and a number
23
+ * as its text, which the core schema reads as an integer or a float. The text
24
+ * ends with a line break.
25
+ *
26
+ * **A string is plain unless it could read as something else.** It is written
27
+ * double-quoted when it is empty; when it reads as null, a boolean or a number
28
+ * under YAML 1.2 or YAML 1.1 (`~`, `null`, `yes`, `on`, `y`, `true` in any
29
+ * case; anything starting with a digit, or a sign or `.` and then a digit;
30
+ * `.inf` and `.nan`, signed or not); when it starts with an indicator (`@`, `` ` ``, `\`, `*`,
31
+ * `&`, `!`, `|`, `>`, `%`, `'`, `"`, `#`, `,`, `[`, `]`, `{`, `}`, or `-`, `?`
32
+ * or `:` before a space or the end) or with `---` or `...`; when it holds
33
+ * `: ` or ` #` or ends in `:`; when it starts or ends with a space; when it
34
+ * holds a control character, a line break, U+2028, U+2029, U+FEFF, U+FFFE or
35
+ * U+FFFF; and, as a key, when it is `<<`, which YAML reads as a merge key.
36
+ * Keys and values follow the same rule. A quoted string escapes `"`, `\` and
37
+ * every character just listed, so it stays on one line. A key whose written
38
+ * form runs past the 1024 bytes YAML allows an implicit key is written as an
39
+ * explicit one, `? key` and then `: value`.
40
+ *
41
+ * **What it answers.** The YAML text, or `""` when `v` names no value or the
42
+ * tree nests deeper than `JSON_WRITER_MAX_DEPTH` collections, the limit
43
+ * `stringify` keeps: a parsed tree never does, and a built one is refused
44
+ * rather than recursed into without bound.
45
+ *
46
+ * A string is written as its UTF-8 bytes. Under Node a string is UTF-16 and
47
+ * each unit is read as a byte, so non-ASCII text differs from the native
48
+ * build, as it does in `nish/json-value`'s builders.
49
+ */
50
+ import { JSON_WRITER_MAX_DEPTH } from "nish/json"
51
+ import {
52
+ JSON_VALUE_ARRAY,
53
+ JSON_VALUE_BOOLEAN,
54
+ JSON_VALUE_NONE,
55
+ JSON_VALUE_NULL,
56
+ JSON_VALUE_NUMBER,
57
+ JSON_VALUE_OBJECT,
58
+ JsonDocument,
59
+ JsonValue,
60
+ } from "nish/json-value"
61
+
62
+ /** The most bytes an implicit key may run before its `:` (YAML 1.2 §7.4.2). */
63
+ const YAML_WRITE_MAX_KEY_LENGTH: i32 = 1024
64
+
65
+ const YAML_WRITE_HEX: string = "0123456789ABCDEF"
66
+
67
+ /** The bytes the writer puts between scalars. */
68
+ const YAML_WRITE_LF: i32 = 10
69
+ const YAML_WRITE_SPACE: i32 = 32
70
+ const YAML_WRITE_QUOTE: i32 = 34
71
+ const YAML_WRITE_COLON: i32 = 58
72
+ const YAML_WRITE_BACKSLASH: i32 = 92
73
+
74
+ /** Byte `i` of `text`, or `-1` past either end. */
75
+ const yamlWriteByte = (text: string, i: i32): i32 =>
76
+ i >= 0 && i < toI32(text.length) ? toI32(text.charCodeAt(i)) : -1
77
+
78
+ const yamlWriteIsDigit = (c: i32): boolean => c >= 48 && c <= 57
79
+
80
+ /** Whether `c` is an indicator that cannot start a plain scalar, whatever follows it. */
81
+ const yamlWriteIsIndicator = (c: i32): boolean =>
82
+ c === 64 ||
83
+ c === 96 ||
84
+ c === 92 ||
85
+ c === 42 ||
86
+ c === 38 ||
87
+ c === 33 ||
88
+ c === 124 ||
89
+ c === 62 ||
90
+ c === 37 ||
91
+ c === 39 ||
92
+ c === 34 ||
93
+ c === 35 ||
94
+ c === 44 ||
95
+ c === 91 ||
96
+ c === 93 ||
97
+ c === 123 ||
98
+ c === 125
99
+
100
+ /** Whether `text` from byte `from` to its end is `word`, ASCII letters in either case. */
101
+ const yamlWriteMatches = (text: string, from: i32, word: string): boolean => {
102
+ const n: i32 = toI32(word.length)
103
+ if (toI32(text.length) - from !== n) {
104
+ return false
105
+ }
106
+ for (let i: i32 = 0; i < n; i += 1) {
107
+ const c: i32 = yamlWriteByte(text, from + i)
108
+ if ((c >= 65 && c <= 90 ? c + 32 : c) !== yamlWriteByte(word, i)) {
109
+ return false
110
+ }
111
+ }
112
+ return true
113
+ }
114
+
115
+ /** Whether `text` is one of the words YAML 1.2 or 1.1 reads as null or a boolean. */
116
+ const yamlWriteIsWord = (text: string): boolean =>
117
+ text === "~" ||
118
+ yamlWriteMatches(text, 0, "null") ||
119
+ yamlWriteMatches(text, 0, "true") ||
120
+ yamlWriteMatches(text, 0, "false") ||
121
+ yamlWriteMatches(text, 0, "yes") ||
122
+ yamlWriteMatches(text, 0, "no") ||
123
+ yamlWriteMatches(text, 0, "on") ||
124
+ yamlWriteMatches(text, 0, "off") ||
125
+ yamlWriteMatches(text, 0, "y") ||
126
+ yamlWriteMatches(text, 0, "n")
127
+
128
+ /** Whether `text` could read as a number: a digit first, or a sign or `.` and then a digit, or `.inf` or `.nan`. */
129
+ const yamlWriteIsNumeric = (text: string): boolean => {
130
+ let i: i32 = 0
131
+ const sign: i32 = yamlWriteByte(text, 0)
132
+ if (sign === 43 || sign === 45) {
133
+ i = 1
134
+ }
135
+ const c: i32 = yamlWriteByte(text, i)
136
+ if (yamlWriteIsDigit(c)) {
137
+ return true
138
+ }
139
+ if (c !== 46) {
140
+ return false
141
+ }
142
+ if (yamlWriteIsDigit(yamlWriteByte(text, i + 1))) {
143
+ return true
144
+ }
145
+ return yamlWriteMatches(text, i, ".inf") || yamlWriteMatches(text, i, ".nan")
146
+ }
147
+
148
+ /**
149
+ * How many bytes of `text` from `i` make one character a plain scalar may not
150
+ * hold and a quoted one escapes: a control character, U+0085 and the other C1
151
+ * controls, U+2028, U+2029, U+FEFF, U+FFFE or U+FFFF; `0` for any other.
152
+ */
153
+ const yamlWriteEscapedLength = (text: string, i: i32): i32 => {
154
+ const c: i32 = yamlWriteByte(text, i)
155
+ if (c < 32 || c === 127) {
156
+ return 1
157
+ }
158
+ const next: i32 = yamlWriteByte(text, i + 1)
159
+ if (c === 194 && next >= 128 && next <= 159) {
160
+ return 2
161
+ }
162
+ const third: i32 = yamlWriteByte(text, i + 2)
163
+ if (c === 226 && next === 128 && (third === 168 || third === 169)) {
164
+ return 3
165
+ }
166
+ if (c === 239 && ((next === 187 && third === 191) || (next === 191 && (third === 190 || third === 191)))) {
167
+ return 3
168
+ }
169
+ return 0
170
+ }
171
+
172
+ /** Whether `text` must be double-quoted to read back as the same string; `key` adds the merge key `<<`. */
173
+ const yamlWriteNeedsQuotes = (text: string, key: boolean): boolean => {
174
+ const n: i32 = toI32(text.length)
175
+ if (n === 0 || yamlWriteIsWord(text) || yamlWriteIsNumeric(text) || (key && text === "<<")) {
176
+ return true
177
+ }
178
+ const first: i32 = yamlWriteByte(text, 0)
179
+ const second: i32 = yamlWriteByte(text, 1)
180
+ if (yamlWriteIsIndicator(first) || first === 32 || yamlWriteByte(text, n - 1) === 32) {
181
+ return true
182
+ }
183
+ if ((first === 45 || first === 63 || first === 58) && (second === 32 || second === -1)) {
184
+ return true
185
+ }
186
+ if (text.startsWith("---") || text.startsWith("...") || yamlWriteByte(text, n - 1) === 58) {
187
+ return true
188
+ }
189
+ for (let i: i32 = 0; i < n; i += 1) {
190
+ const c: i32 = yamlWriteByte(text, i)
191
+ const next: i32 = yamlWriteByte(text, i + 1)
192
+ if ((c === 58 && next === 32) || (c === 32 && next === 35) || yamlWriteEscapedLength(text, i) > 0) {
193
+ return true
194
+ }
195
+ }
196
+ return false
197
+ }
198
+
199
+ /**
200
+ * How many bytes `text` takes as written: its own, or quoted, two more for the
201
+ * quotes and, for each escape, the bytes it adds to the character it replaces.
202
+ */
203
+ const yamlWriteLength = (text: string, quoted: boolean): i32 => {
204
+ const n: i32 = toI32(text.length)
205
+ if (!quoted) {
206
+ return n
207
+ }
208
+ let length: i32 = n + 2
209
+ let i: i32 = 0
210
+ while (i < n) {
211
+ const c: i32 = yamlWriteByte(text, i)
212
+ const escaped: i32 = yamlWriteEscapedLength(text, i)
213
+ if (c === 34 || c === 92 || c === 10 || c === 9 || c === 13) {
214
+ length += 1
215
+ } else if (escaped === 1) {
216
+ length += 3
217
+ } else if (escaped > 1) {
218
+ length += escaped
219
+ }
220
+ i += escaped > 1 ? escaped : 1
221
+ }
222
+ return length
223
+ }
224
+
225
+ /** Writes one JSON value as block YAML, byte by byte, into `out`. */
226
+ class YamlWriter {
227
+ doc: JsonDocument
228
+ out: u8[]
229
+ /** Whether a collection nested past `JSON_WRITER_MAX_DEPTH`. */
230
+ tooDeep: boolean = false
231
+
232
+ constructor(doc: JsonDocument) {
233
+ this.doc = doc
234
+ this.out = []
235
+ }
236
+
237
+ byte(c: i32): void {
238
+ this.out.push(toU8(c))
239
+ }
240
+
241
+ /** Writes the bytes of `text` from `from` up to `to`. */
242
+ bytes(text: string, from: i32, to: i32): void {
243
+ for (let i: i32 = from; i < to; i += 1) {
244
+ this.byte(yamlWriteByte(text, i))
245
+ }
246
+ }
247
+
248
+ text(text: string): void {
249
+ const from: i32 = 0
250
+ this.bytes(text, from, toI32(text.length))
251
+ }
252
+
253
+ /** Writes `count` spaces. */
254
+ spaces(count: i32): void {
255
+ for (let i: i32 = 0; i < count; i += 1) {
256
+ this.byte(YAML_WRITE_SPACE)
257
+ }
258
+ }
259
+
260
+ /** Writes `\xXX` for byte `c`. */
261
+ hex(c: i32): void {
262
+ this.text("\\x")
263
+ this.byte(yamlWriteByte(YAML_WRITE_HEX, c >> 4))
264
+ this.byte(yamlWriteByte(YAML_WRITE_HEX, c & 15))
265
+ }
266
+
267
+ /** Writes the escape for the `length` bytes at `i`, a character yamlWriteEscapedLength names. */
268
+ escape(text: string, i: i32, length: i32): void {
269
+ const c: i32 = yamlWriteByte(text, i)
270
+ const second: i32 = yamlWriteByte(text, i + 1)
271
+ const third: i32 = yamlWriteByte(text, i + 2)
272
+ if (length === 2) {
273
+ this.hex(second)
274
+ } else if (length === 3 && second === 128) {
275
+ this.text(third === 168 ? "\\u2028" : "\\u2029")
276
+ } else if (length === 3 && second === 187) {
277
+ this.text("\\uFEFF")
278
+ } else if (length === 3) {
279
+ this.text(third === 190 ? "\\uFFFE" : "\\uFFFF")
280
+ } else if (c === 10) {
281
+ this.text("\\n")
282
+ } else if (c === 9) {
283
+ this.text("\\t")
284
+ } else if (c === 13) {
285
+ this.text("\\r")
286
+ } else {
287
+ this.hex(c)
288
+ }
289
+ }
290
+
291
+ /** Writes `text` as a double-quoted scalar on one line. */
292
+ quoted(text: string): void {
293
+ const n: i32 = toI32(text.length)
294
+ this.byte(YAML_WRITE_QUOTE)
295
+ let i: i32 = 0
296
+ while (i < n) {
297
+ const c: i32 = yamlWriteByte(text, i)
298
+ const length: i32 = yamlWriteEscapedLength(text, i)
299
+ if (c === 34 || c === 92) {
300
+ this.byte(YAML_WRITE_BACKSLASH)
301
+ this.byte(c)
302
+ i += 1
303
+ } else if (length > 0) {
304
+ this.escape(text, i, length)
305
+ i += length
306
+ } else {
307
+ this.byte(c)
308
+ i += 1
309
+ }
310
+ }
311
+ this.byte(YAML_WRITE_QUOTE)
312
+ }
313
+
314
+ /** Writes `text` as a scalar: plain when that reads back as the same string, double-quoted otherwise. */
315
+ string(text: string, quoted: boolean): void {
316
+ if (quoted) {
317
+ this.quoted(text)
318
+ } else {
319
+ this.text(text)
320
+ }
321
+ }
322
+
323
+ /** Whether `v` is a collection with members, which takes lines of its own. */
324
+ isBlock(v: JsonValue): boolean {
325
+ const kind: i32 = this.doc.kind(v)
326
+ return (kind === JSON_VALUE_ARRAY || kind === JSON_VALUE_OBJECT) && this.doc.length(v) > 0
327
+ }
328
+
329
+ /** Writes `v` on one line: a scalar, `{}` or `[]`. */
330
+ inline(v: JsonValue): void {
331
+ const doc: JsonDocument = this.doc
332
+ const kind: i32 = doc.kind(v)
333
+ if (kind === JSON_VALUE_NULL) {
334
+ this.text("null")
335
+ } else if (kind === JSON_VALUE_BOOLEAN) {
336
+ this.text(doc.boolean(v) ? "true" : "false")
337
+ } else if (kind === JSON_VALUE_NUMBER) {
338
+ this.text(doc.numberText(v))
339
+ } else if (kind === JSON_VALUE_ARRAY) {
340
+ this.text("[]")
341
+ } else if (kind === JSON_VALUE_OBJECT) {
342
+ this.text("{}")
343
+ } else {
344
+ const text: string = doc.string(v)
345
+ this.string(text, yamlWriteNeedsQuotes(text, false))
346
+ }
347
+ }
348
+
349
+ /**
350
+ * Writes `v` starting at column `indent`, where the line has already reached
351
+ * it, and ends its last line; `depth` is how many collections hold it.
352
+ */
353
+ node(v: JsonValue, indent: i32, depth: i32): void {
354
+ const doc: JsonDocument = this.doc
355
+ const kind: i32 = doc.kind(v)
356
+ if ((kind === JSON_VALUE_ARRAY || kind === JSON_VALUE_OBJECT) && depth >= JSON_WRITER_MAX_DEPTH) {
357
+ this.tooDeep = true
358
+ return
359
+ }
360
+ if (!this.isBlock(v)) {
361
+ this.inline(v)
362
+ this.byte(YAML_WRITE_LF)
363
+ return
364
+ }
365
+ const object: boolean = kind === JSON_VALUE_OBJECT
366
+ for (let i: i32 = 0; i < doc.length(v) && !this.tooDeep; i += 1) {
367
+ if (i > 0) {
368
+ this.spaces(indent)
369
+ }
370
+ const member: JsonValue = doc.at(v, i)
371
+ if (!object) {
372
+ this.text("- ")
373
+ this.node(member, indent + 2, depth + 1)
374
+ continue
375
+ }
376
+ const key: string = doc.keyAt(v, i)
377
+ const quoted: boolean = yamlWriteNeedsQuotes(key, true)
378
+ const explicit: boolean = yamlWriteLength(key, quoted) > YAML_WRITE_MAX_KEY_LENGTH
379
+ if (explicit) {
380
+ this.text("? ")
381
+ }
382
+ this.string(key, quoted)
383
+ if (explicit) {
384
+ this.byte(YAML_WRITE_LF)
385
+ this.spaces(indent)
386
+ }
387
+ this.byte(YAML_WRITE_COLON)
388
+ if (this.isBlock(member)) {
389
+ this.byte(YAML_WRITE_LF)
390
+ this.spaces(indent + 2)
391
+ } else {
392
+ this.byte(YAML_WRITE_SPACE)
393
+ }
394
+ this.node(member, indent + 2, depth + 1)
395
+ }
396
+ }
397
+ }
398
+
399
+ /**
400
+ * `v` of `doc` as block YAML text that `parseYaml` reads back as the same
401
+ * tree; `""` when `v` names no value or nests deeper than
402
+ * `JSON_WRITER_MAX_DEPTH` collections. See the module comment for the rule
403
+ * that quotes a string.
404
+ */
405
+ export const stringifyYaml = (doc: JsonDocument, v: JsonValue): string => {
406
+ if (doc.kind(v) === JSON_VALUE_NONE) {
407
+ return ""
408
+ }
409
+ const writer: YamlWriter = new YamlWriter(doc)
410
+ const indent: i32 = 0
411
+ const depth: i32 = 0
412
+ writer.node(v, indent, depth)
413
+ const from: i32 = 0
414
+ return writer.tooDeep ? "" : String.fromBytes(writer.out, from, toI32(writer.out.length))
415
+ }