@amritk/nish-aarch64-darwin 0.34.1 → 0.36.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 +22 -13
- package/bin/nish +0 -0
- package/docs/AI.md +86 -16
- package/package.json +1 -1
- package/runtime/async.d.mts +49 -0
- package/runtime/async.mjs +27 -0
- package/runtime/nish.d.ts +4681 -427
- 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/runtime/vite.d.ts +30 -0
- package/runtime/vite.mjs +150 -0
- package/scripts/build.sh +108 -13
- package/std/README.md +131 -131
- package/std/base64.ts +34 -5
- package/std/bytes.ts +258 -42
- package/std/cli-args.ts +296 -70
- package/std/cli-flags.ts +184 -19
- package/std/cli.ts +475 -54
- package/std/collections.ts +121 -23
- package/std/compress/checksum.ts +44 -14
- package/std/compress/deflate.ts +224 -111
- package/std/compress/gzip.ts +217 -53
- package/std/compress/zlib.ts +63 -7
- package/std/crypto/aes.ts +80 -9
- package/std/crypto/base64url.ts +22 -0
- package/std/crypto/bcrypt-batch.ts +88 -21
- package/std/crypto/bcrypt.ts +60 -0
- package/std/crypto/chacha20poly1305.ts +53 -0
- package/std/crypto/ct.ts +32 -13
- package/std/crypto/ed25519.ts +47 -0
- package/std/crypto/hkdf.ts +198 -13
- package/std/crypto/hmac.ts +235 -31
- package/std/crypto/jwt.ts +192 -63
- package/std/crypto/p256.ts +159 -16
- package/std/crypto/p384.ts +28 -3
- package/std/crypto/pki-roots.ts +32 -2
- package/std/crypto/pki.ts +81 -15
- package/std/crypto/rsa.ts +33 -3
- package/std/crypto/sha1.ts +3 -0
- package/std/crypto/sha256.ts +24 -1
- package/std/crypto/sha512.ts +99 -14
- package/std/crypto/x25519.ts +152 -14
- package/std/crypto/x509-random.ts +10 -0
- package/std/crypto/x509.ts +67 -7
- package/std/json-equal.ts +19 -0
- package/std/json-format.ts +112 -13
- package/std/json-number.ts +64 -14
- package/std/json-pointer.ts +23 -1
- package/std/json-tokenizer.ts +100 -29
- package/std/json-typed.ts +713 -66
- package/std/json-value.ts +400 -124
- package/std/json.ts +138 -10
- package/std/map.ts +25 -7
- package/std/math.ts +36 -4
- package/std/net/buffer-pool.ts +42 -11
- package/std/net/dns-config.ts +109 -23
- package/std/net/dns-message.ts +62 -7
- package/std/net/dns-resolver.ts +247 -53
- package/std/net/dns.ts +203 -35
- package/std/net/fetch.ts +151 -61
- package/std/net/handler.ts +278 -80
- package/std/net/hpack.ts +262 -52
- package/std/net/http-compress.ts +125 -15
- package/std/net/http-fields.ts +85 -9
- package/std/net/http1-client-codec.ts +100 -19
- package/std/net/http1-codec.ts +297 -77
- package/std/net/http1-server.ts +430 -94
- package/std/net/http2-frame.ts +272 -35
- package/std/net/http2-tls.ts +135 -34
- package/std/net/http2.ts +247 -106
- package/std/net/http3-frame.ts +154 -17
- package/std/net/http3-server.ts +275 -101
- package/std/net/http3.ts +307 -115
- package/std/net/outbound.ts +37 -3
- package/std/net/postgres-carrier.ts +144 -8
- package/std/net/postgres.ts +801 -112
- package/std/net/prefork.ts +164 -31
- package/std/net/qpack.ts +105 -18
- package/std/net/quic-conn-ack.ts +59 -12
- package/std/net/quic-conn-cid.ts +124 -27
- package/std/net/quic-conn-params.ts +70 -10
- package/std/net/quic-datagram.ts +43 -3
- package/std/net/quic-frame.ts +286 -12
- package/std/net/quic-listener.ts +101 -32
- package/std/net/quic-packet.ts +302 -21
- package/std/net/quic-recovery.ts +264 -52
- package/std/net/quic-stream.ts +353 -91
- package/std/net/quic.ts +1124 -201
- package/std/net/router.ts +87 -40
- package/std/net/tls/client.ts +166 -51
- package/std/net/tls/codec.ts +413 -56
- package/std/net/tls/record-client.ts +110 -55
- package/std/net/tls/record-server.ts +159 -59
- package/std/net/tls/record.ts +109 -12
- package/std/net/tls/schedule.ts +235 -26
- package/std/net/tls/ticket.ts +159 -40
- package/std/net/tls/verify.ts +49 -3
- package/std/net/tls-tcp.ts +250 -45
- package/std/net/tls.ts +221 -59
- package/std/net/upstream.ts +81 -45
- package/std/net/url.ts +97 -13
- package/std/net/websocket.ts +122 -12
- package/std/net/webtransport.ts +220 -89
- package/std/pair.ts +10 -2
- package/std/random.ts +34 -9
- package/std/regex.ts +352 -198
- package/std/region.ts +70 -15
- package/std/secret.ts +52 -11
- package/std/sort.ts +17 -2
- package/std/sqlite.ts +256 -35
- package/std/sync/ring.ts +430 -40
- package/std/sync/shm.ts +222 -15
- package/std/term-io.ts +137 -64
- package/std/term-pixels.ts +144 -19
- package/std/term-probe.ts +66 -25
- package/std/term-rate.ts +128 -57
- package/std/term.ts +332 -121
- package/std/testing.ts +130 -32
- package/std/text.ts +73 -7
- package/std/threads.ts +229 -41
- package/std/yaml-json.ts +94 -82
- package/std/yaml-lines.ts +47 -15
- package/std/yaml-write.ts +24 -16
- package/std/yaml.ts +764 -384
package/INSTALL.md
CHANGED
|
@@ -52,7 +52,14 @@ export PATH="$(brew --prefix llvm@18)/bin:$PATH" # add to your shell profile
|
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
Xcode's `clang` (`xcode-select --install`) also works for native binaries;
|
|
55
|
-
the Homebrew LLVM is needed for the `wasm` and `wasi` profiles (`wasm-ld`).
|
|
55
|
+
the Homebrew LLVM is needed for the `wasm`, `wasm-host` and `wasi` profiles (`wasm-ld`).
|
|
56
|
+
|
|
57
|
+
`wasm-opt` (binaryen: `apt-get install binaryen`, `brew install binaryen`) is
|
|
58
|
+
optional. When it is on `PATH`, `scripts/build.sh --profile wasm-host` runs
|
|
59
|
+
`wasm-opt -Oz` on the module, and the build line says whether it ran. Without
|
|
60
|
+
it the module is complete, just not as small.
|
|
61
|
+
|
|
62
|
+
<a id="wasi-optional-for---profile-wasi" style="scroll-margin-top: 65px"></a>
|
|
56
63
|
|
|
57
64
|
### WASI (optional, for `--profile wasi`)
|
|
58
65
|
|
|
@@ -105,7 +112,7 @@ of its own architecture by the release workflow before the release existed, and
|
|
|
105
112
|
installing is a download and an unpack.
|
|
106
113
|
|
|
107
114
|
Through npm, which is also how an Nish *program* resolves its dependencies
|
|
108
|
-
([wp21-packages.md](wp21-packages.md)), so this is the one to pick if you want
|
|
115
|
+
([wp21-packages.md](https://github.com/amritk/nish/blob/main/docs/wp21-packages.md)), so this is the one to pick if you want
|
|
109
116
|
the compiler pinned per project in a `package.json`:
|
|
110
117
|
|
|
111
118
|
```bash
|
|
@@ -169,7 +176,7 @@ release also attaches `nish-<version>.spdx.json`, an SPDX 2.3 software bill of
|
|
|
169
176
|
materials: every attached file with its SHA-256, the clang, linker, Node.js
|
|
170
177
|
and seed compiler that built each tarball (recorded by the build row itself),
|
|
171
178
|
and the vendored code from
|
|
172
|
-
[THIRD_PARTY_NOTICES.md](
|
|
179
|
+
[THIRD_PARTY_NOTICES.md](https://github.com/amritk/nish/blob/main/THIRD_PARTY_NOTICES.md) that each of them contains.
|
|
173
180
|
How these fit the rest of the release's defences is
|
|
174
181
|
[docs/security/supply-chain.md](security/supply-chain.md).
|
|
175
182
|
|
|
@@ -198,13 +205,13 @@ never fails over it.
|
|
|
198
205
|
> installers above handle it by running the binary through a one-line `exec` of
|
|
199
206
|
> an absolute path. If you unpack a tarball by hand, invoke it by path
|
|
200
207
|
> (`nish-<version>-<asset>/bin/nish`) or write that wrapper yourself. The
|
|
201
|
-
> underlying defect is [wp19 §5a](wp19-stage0-retirement.md#5a-what-r6-is-waiting-on)
|
|
208
|
+
> underlying defect is [wp19 §5a](https://github.com/amritk/nish/blob/main/docs/wp19-stage0-retirement.md#5a-what-r6-is-waiting-on)
|
|
202
209
|
> item 4.
|
|
203
210
|
|
|
204
211
|
**The package is `nish` from 0.20.0.** Releases up to 0.18.0 were published
|
|
205
212
|
as `@amritk/nish` (0.19.0's publish to npm failed), which is deprecated and
|
|
206
213
|
points here; `npm install -g nish`
|
|
207
|
-
replaces it ([docs/wp12-release.md](wp12-release.md#the-npm-name)). Versions
|
|
214
|
+
replaces it ([docs/wp12-release.md](https://github.com/amritk/nish/blob/main/docs/wp12-release.md#the-npm-name)). Versions
|
|
208
215
|
0.0.0 and 0.0.1 of `nish` are an unrelated 2014 project that held the name
|
|
209
216
|
before it, so pin `nish@^0.20.0` or later rather than an older range.
|
|
210
217
|
|
|
@@ -233,9 +240,9 @@ nish: no prebuilt compiler for freebsd/x64
|
|
|
233
240
|
Until 0.6.0 it ran the TypeScript compiler that shipped in the same package
|
|
234
241
|
instead — the same compiler by every test here, about eight times slower, and
|
|
235
242
|
no C toolchain needed. That compiler was stage0, which was deleted in R6
|
|
236
|
-
([wp19](wp19-stage0-retirement.md)), so there is nothing left in the package to
|
|
243
|
+
([wp19](https://github.com/amritk/nish/blob/main/docs/wp19-stage0-retirement.md)), so there is nothing left in the package to
|
|
237
244
|
fall back to. The cost is stated where the rest of that deletion's costs are,
|
|
238
|
-
in [wp19 §6](wp19-stage0-retirement.md#6-what-retirement-costs-stated-plainly),
|
|
245
|
+
in [wp19 §6](https://github.com/amritk/nish/blob/main/docs/wp19-stage0-retirement.md#6-what-retirement-costs-stated-plainly),
|
|
239
246
|
and it is a real one: **musl, FreeBSD and 32-bit platforms have no `npm
|
|
240
247
|
install` route to a compiler any more.**
|
|
241
248
|
|
|
@@ -276,7 +283,7 @@ to have on the issue tracker rather than a workaround to discover here.
|
|
|
276
283
|
`nish` from 0.20.0; 0.19.0 is on GitHub only, because its npm publish
|
|
277
284
|
failed. Every release publishes the main package and its platform packages to
|
|
278
285
|
npm from `release.yml`, by trusted publishing
|
|
279
|
-
([docs/wp12-release.md](wp12-release.md#release-procedure) step 4), so
|
|
286
|
+
([docs/wp12-release.md](https://github.com/amritk/nish/blob/main/docs/wp12-release.md#release-procedure) step 4), so
|
|
280
287
|
`npm install -g nish` is the whole install. The rest of this section is
|
|
281
288
|
for a machine that cannot reach the registry, or a release before 0.10.0.
|
|
282
289
|
|
|
@@ -358,7 +365,7 @@ v0.16.0; v0.1.1 was the first release with a binary attached.
|
|
|
358
365
|
The `v0.1.0` tag exists but has no release behind it and no assets, so every
|
|
359
366
|
`v0.1.0` download URL is a 404 — the tag was pushed by a workflow, and GitHub
|
|
360
367
|
raises no event for that, so nothing ever built it
|
|
361
|
-
([docs/wp12-release.md](wp12-release.md#release-procedure) step 2). When a newer
|
|
368
|
+
([docs/wp12-release.md](https://github.com/amritk/nish/blob/main/docs/wp12-release.md#release-procedure) step 2). When a newer
|
|
362
369
|
release exists, take its version from
|
|
363
370
|
[the releases page](https://github.com/amritk/nish/releases/latest).
|
|
364
371
|
|
|
@@ -435,7 +442,7 @@ over, `runtime-checksum.c` the CRC-32 kernels of `nish/compress/checksum`,
|
|
|
435
442
|
`runtime-sandbox.c` the confinement a `--sandbox` build applies, and
|
|
436
443
|
`runtime-shm.c` the shared-memory regions of `nish/sync/shm`.
|
|
437
444
|
They are separate so that each carries its own measured size ceiling
|
|
438
|
-
([docs/wp7-runtime.md](wp7-runtime.md)); nothing in the core calls into the
|
|
445
|
+
([docs/wp7-runtime.md](https://github.com/amritk/nish/blob/main/docs/wp7-runtime.md)); nothing in the core calls into the
|
|
439
446
|
others, so a line that names only `runtime.c` and `runtime-os.c` still links a
|
|
440
447
|
program that uses none of the other nine. `scripts/build.sh` compiles the other
|
|
441
448
|
nine beside any
|
|
@@ -451,7 +458,7 @@ beside `-DNISH_THREADS=1`).
|
|
|
451
458
|
## 2a. What `npm run build` does
|
|
452
459
|
|
|
453
460
|
`src/` is the compiler, written in Nish, and it compiles itself
|
|
454
|
-
([docs/wp14-selfhost.md](wp14-selfhost.md)). From a checkout, with clang on
|
|
461
|
+
([docs/wp14-selfhost.md](https://github.com/amritk/nish/blob/main/docs/wp14-selfhost.md)). From a checkout, with clang on
|
|
455
462
|
`PATH`, `npm run build` runs `scripts/bootstrap.sh` with the seed from §2:
|
|
456
463
|
|
|
457
464
|
```bash
|
|
@@ -486,7 +493,7 @@ in `src/` and becomes usable inside `src/` from the next release on; CI's
|
|
|
486
493
|
`bootstrap` job is what checks that the released seed still builds stage1.
|
|
487
494
|
Until R6 the seed was a TypeScript compiler, stage0, run under Node; it was
|
|
488
495
|
deleted once the native one answered every flag it did
|
|
489
|
-
([wp19](wp19-stage0-retirement.md)).
|
|
496
|
+
([wp19](https://github.com/amritk/nish/blob/main/docs/wp19-stage0-retirement.md)).
|
|
490
497
|
|
|
491
498
|
## 3. Hello world
|
|
492
499
|
|
|
@@ -518,7 +525,7 @@ nish hello.ts -o hello.ll
|
|
|
518
525
|
|
|
519
526
|
Other build profiles: `--profile size` (smallest binary), `--profile debug`
|
|
520
527
|
(no optimisation, symbols kept). Run `nish --help` for every flag, and
|
|
521
|
-
see the [README](
|
|
528
|
+
see the [README](https://github.com/amritk/nish/blob/main/README.md) for the language subset.
|
|
522
529
|
|
|
523
530
|
To use a program as a script rather than keep the binary, run it:
|
|
524
531
|
|
|
@@ -549,6 +556,8 @@ it cannot make private, compiles the runtime itself as it always did; the
|
|
|
549
556
|
wasi profile and `scripts/build.sh` called directly never use the cache.
|
|
550
557
|
Removing the directory is always safe.
|
|
551
558
|
|
|
559
|
+
<a id="4-exit-codes" style="scroll-margin-top: 65px"></a>
|
|
560
|
+
|
|
552
561
|
## 4. Exit codes
|
|
553
562
|
|
|
554
563
|
| Code | Meaning |
|
package/bin/nish
CHANGED
|
Binary file
|
package/docs/AI.md
CHANGED
|
@@ -108,7 +108,9 @@ the difference is a row of [the user guide's table](guide/using-nish/to-typescri
|
|
|
108
108
|
or a bug in `nish` worth reporting. A program on `nish:net`, the signal
|
|
109
109
|
descriptor or a C declaration (NL4010, NL4011), a compound assignment whose
|
|
110
110
|
index would run twice (NL4012) or a generic whose element type decides its
|
|
111
|
-
code (NL4013, NL4014) is refused and has no TypeScript to run.
|
|
111
|
+
code (NL4013, NL4014) is refused and has no TypeScript to run. An `async`
|
|
112
|
+
program is written as Node async/await, whose spawned tasks may print in
|
|
113
|
+
another order than native.
|
|
112
114
|
|
|
113
115
|
Two more surfaces worth knowing: `nish --emit-ast f.ts` prints what was parsed
|
|
114
116
|
and `nish --emit-checked f.ts` prints the side tables the emitter reads. Both
|
|
@@ -140,7 +142,11 @@ everywhere, a template literal instead of `String(n)`.
|
|
|
140
142
|
- A module is one `.ts` file. At the top level it may hold **only**
|
|
141
143
|
declarations: `const` arrows (functions), `class`, `interface`, module
|
|
142
144
|
`const`s, `type` aliases, numeric `enum`s, and `import`s. There is no
|
|
143
|
-
top-level code, so there is no initialisation order to think about.
|
|
145
|
+
top-level code, so there is no initialisation order to think about. The
|
|
146
|
+
one exception is an entry module with no `main`: its top-level statements
|
|
147
|
+
run as `main` (`docs/LANGUAGE.md` → "Top-level code"). Declare every
|
|
148
|
+
function above the first statement, and pass a function what it needs
|
|
149
|
+
rather than naming a variable of the code.
|
|
144
150
|
- `export const main` lives in the entry module only, takes no parameters, and
|
|
145
151
|
returns `void` or an `i32`-lowered `number` — the process exit code. Under
|
|
146
152
|
`--number-mode f64`, declare it `main(): i32`.
|
|
@@ -175,12 +181,12 @@ rejects. This table is the highest-value part of the page.
|
|
|
175
181
|
| `h.get<i32>(7)` (type argument at a method call) | `Type arguments are not written at a call site in Nish` | `h.get(7)` — a generic method infers like a generic function |
|
|
176
182
|
| `<T>(p: T) => p.x` (a member of a type parameter) | `` Cannot read `x` of `T`: an unconstrained type parameter has no members `` | `<T extends Point>(p: T) => p.x`, where `Point` is a class or interface that declares `x` |
|
|
177
183
|
| `identity<i32>(7)` (type argument at a call) | `Type arguments are not written at a call site in Nish` | `identity(7)` — `T` is inferred from the arguments |
|
|
178
|
-
|
|
|
184
|
+
| a promise in a variable, `.then`, `Promise.all` | forbidden: a promise is never a value | `await` each call where it is made; see [Async functions](#async-functions) |
|
|
179
185
|
| `namespace N { }`, `declare global { }`, `@decorator` | forbidden | one module per file; a plain function in place of a decorator |
|
|
180
186
|
| `keyof T`, `<T = i32>` (a default type argument) | `` Unsupported type `keyof T` (Phase 1 supports …) `` / `a default type argument … is not supported` | name the type; a type argument is always inferred |
|
|
181
187
|
| `class B extends A` | `` `extends` is not supported: Nish has no inheritance `` | repeat the fields and `implements` an interface |
|
|
182
188
|
| `static` members, `get x()` / `set x(v)` | `` … `static` members are not supported `` / `` Getters and setters are not supported in class `C` (use a method) `` | module `const`s and plain methods |
|
|
183
|
-
| `const [a, b] = xs`, `({ x }: Point) =>`, `(n?: i32)`, `(n = 1)`, `f(...xs)` | `Destructuring is not supported` / `Destructured parameters are not supported` / `Optional parameters are not supported` / `` Parameter `n` has a default and no type annotation `` / `Spread arguments are not supported` | one name per binding; `n: i32 = 1` (a constant or an earlier parameter) for a default; `...ns: i32[]` as the last parameter, or pass the array itself |
|
|
189
|
+
| `const [a, b] = xs`, `({ x }: Point) =>`, `(n?: i32)`, `(n = 1)`, `f(...xs)` | `Destructuring is not supported` / `Destructured parameters are not supported` / `Optional parameters are not supported` / `` Parameter `n` has a default and no type annotation `` / `Spread arguments are not supported` | one name per binding; `n: i32 = 1` (a constant or an earlier parameter) for a default, `o: Opts | null = null` for an options argument; `...ns: i32[]` as the last parameter, or pass the array itself |
|
|
184
190
|
| `function f(): void;` (an overload), `export default function ()` | `Functions must have a body` / `Functions must be named` | one named function, with its body |
|
|
185
191
|
| a method in an `interface` | `` Interface `I` cannot declare methods (interfaces describe layout only) `` | fields only; a top-level function over the interface |
|
|
186
192
|
| `abstract class`, `declare class`, `constructor(public x: i32)`, `interface B extends A`, `[k: string]: T` | `Abstract classes are not supported` / `` `declare class` is not supported `` / `Parameter properties … are not supported; declare the field and assign it` / ``Interface inheritance (`extends`) is not supported; list every field`` / `Index signatures are not supported …` | a plain class with its fields declared and assigned in the constructor; every field listed; a `Map` for a keyed table |
|
|
@@ -583,8 +589,11 @@ const double = (n: i32): i32 => n * 2; // a concise body is that one `return`
|
|
|
583
589
|
- **Parameters are immutable**: `p = 1`, `p++`, `p += 1` are all rejected. Copy
|
|
584
590
|
into a `let` first.
|
|
585
591
|
- A non-`void` function must return on every path.
|
|
586
|
-
- Rejected: generators, `async`, destructured
|
|
587
|
-
parameters, overloads, nested function declarations.
|
|
592
|
+
- Rejected: generators, a method that is `async`, destructured and optional
|
|
593
|
+
(`x?: T`) parameters, overloads, nested function declarations. A default
|
|
594
|
+
(`n: i32 = 1`) or a rest parameter (`...ns: i32[]`) is allowed on a
|
|
595
|
+
function, a method, a constructor or a module `const` arrow — see
|
|
596
|
+
"Optional parameters" in [Recipes for what is missing](#recipes-for-what-is-missing). Type parameters *are*
|
|
588
597
|
allowed — see [Generic functions](#generic-functions).
|
|
589
598
|
|
|
590
599
|
### Generic functions
|
|
@@ -850,8 +859,8 @@ export const main = (): i32 => {
|
|
|
850
859
|
(`(x) => { if (x > limit) { hits.push(x) } }`); each capture becomes one more
|
|
851
860
|
argument of the direct call. It may not assign to one, read a `let`
|
|
852
861
|
(`` The arrow reads `k`, a `let` of the function it is written in: ... bind the value to a `const` before the call ``),
|
|
853
|
-
read `this` (bind `const self = this`), or read a function parameter
|
|
854
|
-
function. An arrow inside another arrow, or given to a method, a
|
|
862
|
+
read `this` (bind `const self = this`), or read a function-typed parameter
|
|
863
|
+
of its function. An arrow inside another arrow, or given to a method, a
|
|
855
864
|
constructor, `expose` or `exposeWith`, captures nothing; `xs.sort(cmp)`'s
|
|
856
865
|
comparator is the exception, and captures as an arrow argument does.
|
|
857
866
|
- **The argument's type must match exactly**: `(x: i32) => i64` for a
|
|
@@ -873,6 +882,52 @@ export const main = (): i32 => {
|
|
|
873
882
|
};
|
|
874
883
|
```
|
|
875
884
|
|
|
885
|
+
### Async functions
|
|
886
|
+
|
|
887
|
+
`async` compiles natively: a function that awaits becomes a frame and a resume
|
|
888
|
+
switch, one that awaits nothing a plain function, and `export async function
|
|
889
|
+
main` runs to its end, then finishes every task it spawned. Nothing waits on
|
|
890
|
+
sockets or timers in this release, so every task runs to completion.
|
|
891
|
+
`--emit-ts` writes it as Node async/await, where `spawn`ed tasks resume in
|
|
892
|
+
Node's order, not the native one. A call
|
|
893
|
+
that can fail answers `Promise<Result<T, E>>`: test the `Result` after the
|
|
894
|
+
`await`. The rules:
|
|
895
|
+
|
|
896
|
+
- `async` goes on a top-level `function` or an arrow, never a method
|
|
897
|
+
(`NL1063`). Its return type is `Promise<T>` (`NL2655`), and `Promise<T>`
|
|
898
|
+
appears nowhere else — not on a parameter, field, local or alias (`NL2654`).
|
|
899
|
+
- **`await` takes a direct call to an `async` function** (`NL2643` for a value,
|
|
900
|
+
`NL2644` for a plain function's call), **at the top of a statement**: alone,
|
|
901
|
+
as a `const`/`let` initializer, after `return`, or right of a plain `=`.
|
|
902
|
+
Anywhere inside a larger expression is `NL2642`, so bind first:
|
|
903
|
+
`const n = await load(1); console.log(n);`.
|
|
904
|
+
- An `async` call that is not awaited is `NL2645`: a promise is never a value.
|
|
905
|
+
No `.then` (`NL2650`), no `Promise.all` (`NL2649`), no `for await`
|
|
906
|
+
(`NL2133`).
|
|
907
|
+
- Several at once: `import { awaitAll, spawn } from "nish:async"`, then
|
|
908
|
+
`const [a, b] = await awaitAll(f(x), g(y))` (two to eight calls, one name
|
|
909
|
+
each, `NL2647`). `spawn(f(x))` starts a task without waiting; `f` answers
|
|
910
|
+
`void` or a `Result` (`NL2646`).
|
|
911
|
+
- No recursion through `await`, direct or mutual (`NL2648`): write a loop.
|
|
912
|
+
- An `async` arrow goes only to a parameter whose function type answers
|
|
913
|
+
`Promise<T>` (`NL2639`), and only an `async` one goes there (`NL2640`).
|
|
914
|
+
- No `async` under a wasm target or `--profile wasi` (`NL2652`).
|
|
915
|
+
- `spawn(f(x))` runs `f` at once, until it first waits on the outside world,
|
|
916
|
+
before it returns; Node runs `f` only to its first `await` and the rest
|
|
917
|
+
after the spawning task yields. Do not rely on either order.
|
|
918
|
+
|
|
919
|
+
```ts nish:err NL2642
|
|
920
|
+
async function load(id: i32): Promise<i32> {
|
|
921
|
+
return id;
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
async function run(): Promise<void> {
|
|
925
|
+
console.log(await load(1));
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
export const main = (): i32 => 0;
|
|
929
|
+
```
|
|
930
|
+
|
|
876
931
|
### Data parallelism: `nish/threads`
|
|
877
932
|
|
|
878
933
|
`parallelMapInto(src, dst, f)` writes `f(src[i])` into `dst[i]`, and
|
|
@@ -1425,6 +1480,13 @@ export const main = (): i32 => {
|
|
|
1425
1480
|
```
|
|
1426
1481
|
|
|
1427
1482
|
- **No body, and it cannot be `export`ed.**
|
|
1483
|
+
- **Not in a `--target wasm32` build, nor an `--emit-dts` one with no
|
|
1484
|
+
`--target`** (NL2666; `--target wasm32-wasi` keeps it): there a function the page
|
|
1485
|
+
supplies is imported from a host module, the page's own TypeScript file
|
|
1486
|
+
named by `--host`, and becomes a wasm import from module `host`. Only
|
|
1487
|
+
scalars, enums and `HostHandle<"kind">` (a nominal `i32` for an object the
|
|
1488
|
+
page keeps) cross; `import { Canvas, fill } from "./host.ts"`, no `type`
|
|
1489
|
+
modifier.
|
|
1428
1490
|
- **A class with a `CPtr` field is a handle class: open one with `using`.**
|
|
1429
1491
|
`using f = new File(p)` closes `f` once at every exit of its block (falling
|
|
1430
1492
|
off the end, `return`, `break`, `continue`, `orReturn()`), so never call the
|
|
@@ -2243,7 +2305,8 @@ backlog)`, `tcpAccept(fd, peer)`, `netRead(fd, buf, off, len)`,
|
|
|
2243
2305
|
`i32`: **a negative number is a failure, not an exception** — `-11` means "would
|
|
2244
2306
|
block, call again", `-32` a peer that has gone (never SIGPIPE), `-98` the port
|
|
2245
2307
|
is in use, `-111` refused, `-22` a bad argument. Every socket is non-blocking,
|
|
2246
|
-
and there is no
|
|
2308
|
+
and there is no callback, and an `async` function cannot wait on a socket yet
|
|
2309
|
+
(its tasks run on an in-process queue): your `main` is the loop. A client calls
|
|
2247
2310
|
`tcpConnect(addr)`, which answers the descriptor while it is still connecting;
|
|
2248
2311
|
wait for it to be writable, then `connectResult(fd)` is 0 or the failure. Buffers
|
|
2249
2312
|
are `u8[]` only; an address is 18 bytes of one (IPv4 as `::ffff:a.b.c.d`, then
|
|
@@ -2254,6 +2317,9 @@ To fetch a URL from a CLI, skip all of this: `nish/net/fetch`'s
|
|
|
2254
2317
|
response's head is in and answers it with `body.readAll(limit)`, or null on a
|
|
2255
2318
|
failure (a `FetchSyncClient` keeps the connection and says why in `error`).
|
|
2256
2319
|
`netRead` / `netWrite` panic on a range outside the buffer.
|
|
2320
|
+
`netWrite2(fd, a, aOff, aLen, b, bOff, bLen)` writes two ranges in one
|
|
2321
|
+
`sendmsg` (a header and a body without a copy) and answers the bytes written,
|
|
2322
|
+
which may stop inside either range; it checks both ranges, the first one first.
|
|
2257
2323
|
`tcpListenFlags(host, port, backlog, flags)` is `tcpListen` with flag 1
|
|
2258
2324
|
`SO_REUSEPORT`, so several listeners, in one process or many, share a port (Linux
|
|
2259
2325
|
spreads the connections), and flag 2 `TCP_NODELAY` on every socket `tcpAccept`
|
|
@@ -2796,13 +2862,16 @@ or `PG_LOST` to `fail(run)` (on a spent handle these do nothing and count in
|
|
|
2796
2862
|
`stray`), and after each call `next(run)` until
|
|
2797
2863
|
`PG_BATCH_NONE`: `PG_BATCH_ROW` (the connection's row answers request `tag`),
|
|
2798
2864
|
then one of `PG_BATCH_DONE`, `PG_BATCH_MISSING` or `PG_BATCH_FAILED` per
|
|
2799
|
-
request.
|
|
2865
|
+
request. `sorted = false` drops `q.ord` from the statement's `order by` (and
|
|
2866
|
+
its Sort node, with `orderBy` empty): rows route as they come, and every last
|
|
2867
|
+
event waits for `end`. The batcher reads no clock: when to take is the loop's choice, or a `PgBatchClock`'s (`PgBatchClockConfig`: `minCount`, `factor` × the moving average of batch sizes, `maxWaitUs`, the idle bypass `lightCount`; defaults are a fixed window), which `takeDue(conn, clock, nowUs, pool.inFlight())` consults after `clock.arrived(nowUs)` per add; `PgBatchTurns` wakes one collecting connection only when its batch is due. (No block;
|
|
2800
2868
|
`tests/postgres/live`'s `batch` scenario runs it against a server, and the user
|
|
2801
2869
|
guide's [PostgreSQL page](guide/using-nish/postgres.md#batching-keyed-reads)
|
|
2802
2870
|
its walk-through.)
|
|
2803
2871
|
|
|
2804
2872
|
**Call another service from a route handler** — there is no `await fetch()`
|
|
2805
|
-
in a handler and no event-loop
|
|
2873
|
+
in a handler (an `async` task does not wait on a socket yet) and no event-loop
|
|
2874
|
+
callback: `nish/net/upstream`'s `Upstream(h,
|
|
2806
2875
|
origin, limits)` is a pool of keep-alive connections to one `http:` origin on
|
|
2807
2876
|
the `HttpHandler`'s own loop. `users.get(req, path)` returns at once — test it
|
|
2808
2877
|
for `UPSTREAM_E_FULL`, which holds nothing — and keeps `req` held; after each
|
|
@@ -2857,9 +2926,10 @@ export const main = (): i32 => {
|
|
|
2857
2926
|
|
|
2858
2927
|
**Optional parameters** — write a default instead: `(n: i32 = 1)`. A default
|
|
2859
2928
|
is a literal, an enum member or an earlier parameter, and the call site fills
|
|
2860
|
-
it in.
|
|
2861
|
-
|
|
2862
|
-
`
|
|
2929
|
+
it in. An options argument is `(opts: Options | null = null)`: `null` is the
|
|
2930
|
+
one default of a `T | null` parameter. `x?: T` is refused. A variable count
|
|
2931
|
+
of one type is a rest parameter, `(...ns: i32[])`, last in the list; a call
|
|
2932
|
+
never spreads (`f(...xs)`), it passes `xs` to an array parameter.
|
|
2863
2933
|
|
|
2864
2934
|
**A calendar, regex, JSON, threads of your own** — not in the language (the
|
|
2865
2935
|
wall clock is `Date.now()`, and that is all of `Date`). Say so rather than
|
|
@@ -2956,8 +3026,8 @@ export const first = (xs: i32[]): i32 => uncheckedGet(xs, 0);
|
|
|
2956
3026
|
A package that must not touch the network says so in `package.json`,
|
|
2957
3027
|
`"nish": { "capabilities": { "deny": ["net"] } }`, and `--deny net` or an
|
|
2958
3028
|
allowlist such as `--allow fs.read,exit` says the same on the command line.
|
|
2959
|
-
The `"nish"` field holds `noPanic` and `
|
|
2960
|
-
written once; anything more is refused (NL3036) rather than skipped. A
|
|
3029
|
+
The `"nish"` field holds `noPanic`, `capabilities` and `host` and nothing
|
|
3030
|
+
else, each written once; anything more is refused (NL3036) rather than skipped. A
|
|
2961
3031
|
program whose `main` — or, in a library or a header build, any export —
|
|
2962
3032
|
reaches more is refused (NL2459), spanned at the first call and naming the
|
|
2963
3033
|
whole chain to the builtin; nothing changes in a program
|
package/package.json
CHANGED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// The declarations of `runtime/async.mjs`, `nish:async` under Node.
|
|
2
|
+
|
|
3
|
+
/** Starts `task` without waiting for it; the launcher waits before it exits. */
|
|
4
|
+
export declare function spawn(task: Promise<void>): void;
|
|
5
|
+
/** Every task's answer, in the order the calls are written, once all of them finish. */
|
|
6
|
+
export declare function awaitAll<A, B>(a: Promise<A>, b: Promise<B>): Promise<[A, B]>;
|
|
7
|
+
export declare function awaitAll<A, B, C>(a: Promise<A>, b: Promise<B>, c: Promise<C>): Promise<[A, B, C]>;
|
|
8
|
+
export declare function awaitAll<A, B, C, D>(
|
|
9
|
+
a: Promise<A>,
|
|
10
|
+
b: Promise<B>,
|
|
11
|
+
c: Promise<C>,
|
|
12
|
+
d: Promise<D>,
|
|
13
|
+
): Promise<[A, B, C, D]>;
|
|
14
|
+
export declare function awaitAll<A, B, C, D, E>(
|
|
15
|
+
a: Promise<A>,
|
|
16
|
+
b: Promise<B>,
|
|
17
|
+
c: Promise<C>,
|
|
18
|
+
d: Promise<D>,
|
|
19
|
+
e: Promise<E>,
|
|
20
|
+
): Promise<[A, B, C, D, E]>;
|
|
21
|
+
export declare function awaitAll<A, B, C, D, E, F>(
|
|
22
|
+
a: Promise<A>,
|
|
23
|
+
b: Promise<B>,
|
|
24
|
+
c: Promise<C>,
|
|
25
|
+
d: Promise<D>,
|
|
26
|
+
e: Promise<E>,
|
|
27
|
+
f: Promise<F>,
|
|
28
|
+
): Promise<[A, B, C, D, E, F]>;
|
|
29
|
+
export declare function awaitAll<A, B, C, D, E, F, G>(
|
|
30
|
+
a: Promise<A>,
|
|
31
|
+
b: Promise<B>,
|
|
32
|
+
c: Promise<C>,
|
|
33
|
+
d: Promise<D>,
|
|
34
|
+
e: Promise<E>,
|
|
35
|
+
f: Promise<F>,
|
|
36
|
+
g: Promise<G>,
|
|
37
|
+
): Promise<[A, B, C, D, E, F, G]>;
|
|
38
|
+
export declare function awaitAll<A, B, C, D, E, F, G, H>(
|
|
39
|
+
a: Promise<A>,
|
|
40
|
+
b: Promise<B>,
|
|
41
|
+
c: Promise<C>,
|
|
42
|
+
d: Promise<D>,
|
|
43
|
+
e: Promise<E>,
|
|
44
|
+
f: Promise<F>,
|
|
45
|
+
g: Promise<G>,
|
|
46
|
+
h: Promise<H>,
|
|
47
|
+
): Promise<[A, B, C, D, E, F, G, H]>;
|
|
48
|
+
/** Waits for every task `spawn` started, the tasks those tasks start included. */
|
|
49
|
+
export declare function settleTasks(): Promise<void>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// `nish:async` under Node (WP49): what `nish --emit-ts` writes an async
|
|
2
|
+
// program against, and what `runtime/nish.mjs` answers `nish:async` with. A
|
|
3
|
+
// file of its own, not `nish/runtime`, because `nish:process` has a `spawn`
|
|
4
|
+
// there already.
|
|
5
|
+
//
|
|
6
|
+
// `awaitAll` is `Promise.all` over its two to eight tasks. `spawn` starts a
|
|
7
|
+
// task without awaiting it and keeps it, so the launcher's `settleTasks` waits
|
|
8
|
+
// for every task started before the process exits, as the native driver
|
|
9
|
+
// drains its queue after `main` answers. Node runs a task only until its first
|
|
10
|
+
// `await` where native runs it until it first waits, so spawned tasks may print
|
|
11
|
+
// in another order (`docs/RUN_UNDER_NODE.md`). A task that throws is Node's
|
|
12
|
+
// unhandled rejection, which exits 1 as a native panic does.
|
|
13
|
+
|
|
14
|
+
const pending = [];
|
|
15
|
+
|
|
16
|
+
export const spawn = (task) => {
|
|
17
|
+
pending.push(task);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const awaitAll = (...tasks) => Promise.all(tasks);
|
|
21
|
+
|
|
22
|
+
export const settleTasks = async () => {
|
|
23
|
+
for (let i = 0; i < pending.length; i++) {
|
|
24
|
+
await pending[i];
|
|
25
|
+
}
|
|
26
|
+
pending.length = 0;
|
|
27
|
+
};
|