@amritk/nish-aarch64-darwin 0.34.0 → 0.35.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/INSTALL.md +16 -12
- package/bin/nish +0 -0
- package/docs/AI.md +77 -14
- package/package.json +1 -1
- package/runtime/async.d.mts +49 -0
- package/runtime/async.mjs +27 -0
- package/runtime/nish.d.ts +72 -0
- package/runtime/nish.h +6 -2
- package/runtime/nish.mjs +4 -0
- package/runtime/runtime-net.c +22 -0
- package/runtime/runtime-shm.c +93 -2
- package/std/README.md +131 -131
- package/std/bytes.ts +28 -5
- package/std/crypto/base64url.ts +42 -21
- package/std/crypto/bcrypt.ts +222 -183
- package/std/net/http1-codec.ts +262 -92
- package/std/net/http1-server.ts +87 -9
- package/std/net/http3-server.ts +30 -6
- package/std/net/postgres.ts +129 -40
- package/std/net/quic-recovery.ts +36 -8
- package/std/net/quic.ts +664 -59
- package/std/sync/ring.ts +236 -16
- package/std/sync/shm.ts +29 -0
package/std/bytes.ts
CHANGED
|
@@ -26,7 +26,10 @@
|
|
|
26
26
|
* inside a call, and after `getU32LE` inlines, LLVM keeps the checks on
|
|
27
27
|
* `off + 1` to `off + 3`, because the guard compares the length truncated to
|
|
28
28
|
* `i32` and the checks compare it unsigned at 64 bits. A loop that needs them
|
|
29
|
-
* gone indexes the bytes itself.
|
|
29
|
+
* gone indexes the bytes itself. `getU64BE`, and with it `getI64BE` and
|
|
30
|
+
* `getF64BE`, is the exception: it checks the whole range once and reads the
|
|
31
|
+
* eight bytes unchecked, which lowers to one load and a byte swap. An offset
|
|
32
|
+
* outside the range still goes byte by byte, so it panics as the others do.
|
|
30
33
|
*
|
|
31
34
|
* The in-range answers are byte for byte those of the copies `std/` keeps for
|
|
32
35
|
* itself: `sha256LoadWord` (`std/crypto/sha256.ts`) for `getU32BE`,
|
|
@@ -91,8 +94,8 @@ export const getU64LE = (b: u8[], off: i32): u64 => {
|
|
|
91
94
|
return v
|
|
92
95
|
}
|
|
93
96
|
|
|
94
|
-
/**
|
|
95
|
-
|
|
97
|
+
/** `getU64BE` a byte at a time, each index checked: the path for an offset whose eight bytes are not all in the array. */
|
|
98
|
+
const getU64BEByByte = (b: u8[], off: i32): u64 => {
|
|
96
99
|
let v = toU64(0)
|
|
97
100
|
for (let i: i32 = 0; i < 8; i++) {
|
|
98
101
|
v = (v << toU64(8)) | toU64(b[off + i])
|
|
@@ -100,6 +103,26 @@ export const getU64BE = (b: u8[], off: i32): u64 => {
|
|
|
100
103
|
return v
|
|
101
104
|
}
|
|
102
105
|
|
|
106
|
+
/**
|
|
107
|
+
* The `u64` whose bytes, most significant first, are `b[off]` to `b[off + 7]`.
|
|
108
|
+
* The fast path's ors are grouped in pairs, which LLVM folds into one load and
|
|
109
|
+
* a `bswap`; a flat chain of eight `or`s stayed byte by byte. The byte loop is
|
|
110
|
+
* its own function so its last load is not merged with the fast path's.
|
|
111
|
+
*/
|
|
112
|
+
export const getU64BE = (b: u8[], off: i32): u64 => {
|
|
113
|
+
if (off >= 0 && off < 2147483640 && off + 8 <= toI32(b.length)) {
|
|
114
|
+
return (
|
|
115
|
+
(toU64(b[off]) << toU64(56)) |
|
|
116
|
+
(toU64(b[off + 1]) << toU64(48)) |
|
|
117
|
+
((toU64(b[off + 2]) << toU64(40)) | (toU64(b[off + 3]) << toU64(32))) |
|
|
118
|
+
((toU64(b[off + 4]) << toU64(24)) |
|
|
119
|
+
(toU64(b[off + 5]) << toU64(16)) |
|
|
120
|
+
((toU64(b[off + 6]) << toU64(8)) | toU64(b[off + 7])))
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
return getU64BEByByte(b, off)
|
|
124
|
+
}
|
|
125
|
+
|
|
103
126
|
/** `getU32LE`'s bits as a two's-complement `i32`. */
|
|
104
127
|
export const getI32LE = (b: u8[], off: i32): i32 => toI32(getU32LE(b, off))
|
|
105
128
|
|
|
@@ -278,7 +301,7 @@ export const skipJsonPlain = (b: u8[], from: i32, to: i32): i32 => {
|
|
|
278
301
|
* panics `copyBytes` before any byte is written. Natively the copy is one
|
|
279
302
|
* `llvm.memmove`.
|
|
280
303
|
*/
|
|
281
|
-
export const copyBytes = (dst: u8[], at: i32, src: u8[], from: i32, count: i32): void => {
|
|
304
|
+
export const copyBytes = (dst: u8[], at: i32, src: readonly u8[], from: i32, count: i32): void => {
|
|
282
305
|
if (count < 0 || at < 0 || from < 0 || at > toI32(dst.length) - count || from > toI32(src.length) - count) {
|
|
283
306
|
panic("copyBytes: the range lies outside an array")
|
|
284
307
|
}
|
|
@@ -402,7 +425,7 @@ const skipJsonPlainWalk = (b: u8[], from: i32, to: i32): i32 => {
|
|
|
402
425
|
}
|
|
403
426
|
|
|
404
427
|
/** `copyBytes`'s walk, once its ranges are checked: forward, or backward when `dst` is `src` and the bytes move up. */
|
|
405
|
-
const copyBytesWalk = (dst: u8[], at: i32, src: u8[], from: i32, count: i32): void => {
|
|
428
|
+
const copyBytesWalk = (dst: u8[], at: i32, src: readonly u8[], from: i32, count: i32): void => {
|
|
406
429
|
if (at <= from) {
|
|
407
430
|
let k: i32 = 0
|
|
408
431
|
while (k < count) {
|
package/std/crypto/base64url.ts
CHANGED
|
@@ -127,8 +127,9 @@ export const base64urlEncode = (data: u8[]): string => {
|
|
|
127
127
|
* one canonical spelling of any byte string — see the module comment for the
|
|
128
128
|
* five refusals.
|
|
129
129
|
*
|
|
130
|
-
*
|
|
131
|
-
* character,
|
|
130
|
+
* Each group of four characters becomes one 24-bit word, six bits a
|
|
131
|
+
* character, which splits into three bytes; a short final group of two or
|
|
132
|
+
* three characters fills the top of the word and gives one or two.
|
|
132
133
|
*/
|
|
133
134
|
export const base64urlDecode = (text: string): u8[] | null => {
|
|
134
135
|
// A text past 2^31 - 1 bytes is refused before `toI32`, which would
|
|
@@ -148,31 +149,51 @@ export const base64urlDecode = (text: string): u8[] | null => {
|
|
|
148
149
|
// short final group; `n * 3 / 4` would overflow for a text over 700 MB.
|
|
149
150
|
const out: u8[] = new Array<u8>((n >> 2) * 3 + (tail === 0 ? 0 : tail - 1))
|
|
150
151
|
const outLen: i32 = toI32(out.length)
|
|
151
|
-
// All ones once any character is outside the alphabet (
|
|
152
|
+
// All ones once any character is outside the alphabet (a sextet of `-1`
|
|
152
153
|
// shifted right by 31), and non-zero once the text ends on a bit that
|
|
153
154
|
// encodes no byte.
|
|
154
155
|
let bad: i32 = 0
|
|
155
|
-
|
|
156
|
-
|
|
156
|
+
// Four characters make one 24-bit word and three bytes, so a full group has
|
|
157
|
+
// no count of waiting bits to test, and its four sextets are independent.
|
|
157
158
|
let j: i32 = 0
|
|
158
|
-
for (let k: i32 = 0; k < n; k
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
j
|
|
159
|
+
for (let k: i32 = 0; k + 3 < n; k += 4) {
|
|
160
|
+
const s0: i32 = base64urlSextetOf(toI32(text.charCodeAt(k)))
|
|
161
|
+
const s1: i32 = base64urlSextetOf(toI32(text.charCodeAt(k + 1)))
|
|
162
|
+
const s2: i32 = base64urlSextetOf(toI32(text.charCodeAt(k + 2)))
|
|
163
|
+
const s3: i32 = base64urlSextetOf(toI32(text.charCodeAt(k + 3)))
|
|
164
|
+
bad = bad | ((s0 | s1 | s2 | s3) >> 31)
|
|
165
|
+
const word: i32 = ((s0 & 63) << 18) | ((s1 & 63) << 12) | ((s2 & 63) << 6) | (s3 & 63)
|
|
166
|
+
// Always true — `out` was sized from the same length — but written out so
|
|
167
|
+
// that the three stores keep no bounds check.
|
|
168
|
+
if (j >= 0 && j + 2 < outLen) {
|
|
169
|
+
out[j] = toU8(word >> 16)
|
|
170
|
+
out[j + 1] = toU8((word >> 8) & 255)
|
|
171
|
+
out[j + 2] = toU8(word & 255)
|
|
171
172
|
}
|
|
173
|
+
j += 3
|
|
174
|
+
}
|
|
175
|
+
// A short final group of two or three characters: one or two bytes, and the
|
|
176
|
+
// four or two bits left over belong to no byte, so they must be zero for `AA`
|
|
177
|
+
// to be the only spelling of a zero byte and `AB` refused (RFC 4648 §3.5).
|
|
178
|
+
if (tail !== 0) {
|
|
179
|
+
const k: i32 = n - tail
|
|
180
|
+
const s0: i32 = base64urlSextetOf(toI32(text.charCodeAt(k)))
|
|
181
|
+
const s1: i32 = base64urlSextetOf(toI32(text.charCodeAt(k + 1)))
|
|
182
|
+
// A third character only when the tail has one; a two-character tail reads
|
|
183
|
+
// its place as `A`, the zero sextet, which adds no bits.
|
|
184
|
+
const s2: i32 = tail === 3 ? base64urlSextetOf(toI32(text.charCodeAt(k + 2))) : 0
|
|
185
|
+
bad = bad | ((s0 | s1 | s2) >> 31)
|
|
186
|
+
const word: i32 = ((s0 & 63) << 18) | ((s1 & 63) << 12) | ((s2 & 63) << 6)
|
|
187
|
+
if (j >= 0 && j < outLen) {
|
|
188
|
+
out[j] = toU8(word >> 16)
|
|
189
|
+
}
|
|
190
|
+
if (tail === 3 && j + 1 >= 0 && j + 1 < outLen) {
|
|
191
|
+
out[j + 1] = toU8((word >> 8) & 255)
|
|
192
|
+
}
|
|
193
|
+
// The bits under the last byte written: sixteen of the word when one byte
|
|
194
|
+
// was, eight when two were.
|
|
195
|
+
bad = bad | (word & (tail === 2 ? 0xffff : 0xff))
|
|
172
196
|
}
|
|
173
|
-
// The two or four bits left over belong to no byte, and must be zero so that
|
|
174
|
-
// `AA` is the only spelling of a zero byte and `AB` is refused (RFC 4648 §3.5).
|
|
175
|
-
bad = bad | (acc & ((1 << bits) - 1))
|
|
176
197
|
if (bad !== 0) {
|
|
177
198
|
return null
|
|
178
199
|
}
|