@bytecodealliance/preview2-shim 0.15.0 → 0.15.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bytecodealliance/preview2-shim",
3
- "version": "0.15.0",
3
+ "version": "0.15.1",
4
4
  "description": "WASI Preview2 shim for JS environments",
5
5
  "author": "Guy Bedford, Eduardo Rodrigues<16357187+eduardomourar@users.noreply.github.com>",
6
6
  "type": "module",
package/types/cli.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ import type { WasiCliEnvironment } from './interfaces/wasi-cli-environment.d.ts';
2
+ import type { WasiCliExit } from './interfaces/wasi-cli-exit.d.ts';
3
+ import type { WasiCliRun } from './interfaces/wasi-cli-run.d.ts';
4
+ import type { WasiCliStderr } from './interfaces/wasi-cli-stderr.d.ts';
5
+ import type { WasiCliStdin } from './interfaces/wasi-cli-stdin.d.ts';
6
+ import type { WasiCliStdout } from './interfaces/wasi-cli-stdout.d.ts';
7
+ import type { WasiCliTerminalInput } from './interfaces/wasi-cli-terminal-input.d.ts';
8
+ import type { WasiCliTerminalOutput } from './interfaces/wasi-cli-terminal-output.d.ts';
9
+ import type { WasiCliTerminalStderr } from './interfaces/wasi-cli-terminal-stderr.d.ts';
10
+ import type { WasiCliTerminalStdin } from './interfaces/wasi-cli-terminal-stdin.d.ts';
11
+ import type { WasiCliTerminalStdout } from './interfaces/wasi-cli-terminal-stdout.d.ts';
12
+
13
+ export const environment: typeof WasiCliEnvironment;
14
+ export const exit: typeof WasiCliExit;
15
+ export const run: typeof WasiCliRun;
16
+ export const stderr: typeof WasiCliStderr;
17
+ export const stdin: typeof WasiCliStdin;
18
+ export const stdout: typeof WasiCliStdout;
19
+ export const terminalInput: typeof WasiCliTerminalInput;
20
+ export const terminalOutput: typeof WasiCliTerminalOutput;
21
+ export const terminalStderr: typeof WasiCliTerminalStderr;
22
+ export const terminalStdin: typeof WasiCliTerminalStdin;
23
+ export const terminalStdout: typeof WasiCliTerminalStdout;
@@ -0,0 +1,5 @@
1
+ import type { WasiClocksMonotonicClock } from './interfaces/wasi-clocks-monotonic-clock.d.ts';
2
+ import type { WasiClocksWallClock } from './interfaces/wasi-clocks-wall-clock.d.ts';
3
+
4
+ export const wallClock: typeof WasiClocksMonotonicClock;
5
+ export const monotonicClock: typeof WasiClocksWallClock;
@@ -0,0 +1,5 @@
1
+ import type { WasiFilesystemPreopens } from './interfaces/wasi-filesystem-preopens.d.ts';
2
+ import type { WasiFilesystemTypes } from './interfaces/wasi-filesystem-types.d.ts';
3
+
4
+ export const preopens: typeof WasiFilesystemPreopens;
5
+ export const types: typeof WasiFilesystemTypes;
@@ -0,0 +1,7 @@
1
+ import type { WasiHttpIncomingHandler } from './interfaces/wasi-http-incoming-handler.d.ts';
2
+ import type { WasiHttpOutgoingHandler } from './interfaces/wasi-http-outgoing-handler.d.ts';
3
+ import type { WasiHttpTypes } from './interfaces/wasi-http-types.d.ts';
4
+
5
+ export const incomingHandler: typeof WasiHttpIncomingHandler;
6
+ export const outgoingHandler: typeof WasiHttpOutgoingHandler;
7
+ export const types: typeof WasiHttpTypes;
@@ -0,0 +1,15 @@
1
+ import type * as WasiCli from "./cli.d.ts";
2
+ import type * as WasiClocks from './clocks.d.ts';
3
+ import type * as WasiFilesystem from './filesystem.d.ts';
4
+ import type * as WasiHttp from "./http.d.ts";
5
+ import type * as WasiIo from "./io.d.ts";
6
+ import type * as WasiRandom from "./random.d.ts";
7
+ import type * as WasiSockets from "./sockets.d.ts";
8
+
9
+ export const cli: typeof WasiCli;
10
+ export const clocks: typeof WasiClocks;
11
+ export const filesystem: typeof WasiFilesystem;
12
+ export const http: typeof WasiHttp;
13
+ export const io: typeof WasiIo;
14
+ export const random: typeof WasiRandom;
15
+ export const sockets: typeof WasiSockets;
@@ -629,6 +629,18 @@ export type Trailers = Fields;
629
629
  export type StatusCode = number;
630
630
  export type Result<T, E> = { tag: 'ok', val: T } | { tag: 'err', val: E };
631
631
 
632
+ export class ResponseOutparam {
633
+ static set(param: ResponseOutparam, response: Result<OutgoingResponse, ErrorCode>): void;
634
+ }
635
+
636
+ export class OutgoingResponse {
637
+ constructor(headers: Headers)
638
+ statusCode(): StatusCode;
639
+ setStatusCode(statusCode: StatusCode): void;
640
+ headers(): Headers;
641
+ body(): OutgoingBody;
642
+ }
643
+
632
644
  export class OutgoingBody {
633
645
  write(): OutputStream;
634
646
  static finish(this_: OutgoingBody, trailers: Trailers | undefined): void;
@@ -640,50 +652,36 @@ export class Fields {
640
652
  get(name: FieldKey): FieldValue[];
641
653
  has(name: FieldKey): boolean;
642
654
  set(name: FieldKey, value: FieldValue[]): void;
643
- delete(name: FieldKey): void;
655
+ 'delete'(name: FieldKey): void;
644
656
  append(name: FieldKey, value: FieldValue): void;
645
657
  entries(): [FieldKey, FieldValue][];
646
658
  clone(): Fields;
647
659
  }
648
660
 
649
- export class FutureIncomingResponse {
650
- subscribe(): Pollable;
651
- get(): Result<Result<IncomingResponse, ErrorCode>, void> | undefined;
652
- }
653
-
654
- export class IncomingRequest {
655
- method(): Method;
656
- pathWithQuery(): string | undefined;
657
- scheme(): Scheme | undefined;
658
- authority(): string | undefined;
659
- headers(): Headers;
660
- consume(): IncomingBody;
661
- }
662
-
663
661
  export class IncomingBody {
664
662
  stream(): InputStream;
665
663
  static finish(this_: IncomingBody): FutureTrailers;
666
664
  }
667
665
 
666
+ export class FutureIncomingResponse {
667
+ subscribe(): Pollable;
668
+ get(): Result<Result<IncomingResponse, ErrorCode>, void> | undefined;
669
+ }
670
+
668
671
  export class FutureTrailers {
669
672
  subscribe(): Pollable;
670
673
  get(): Result<Result<Trailers | undefined, ErrorCode>, void> | undefined;
671
674
  }
672
675
 
673
- export class IncomingResponse {
674
- status(): StatusCode;
676
+ export class IncomingRequest {
677
+ method(): Method;
678
+ pathWithQuery(): string | undefined;
679
+ scheme(): Scheme | undefined;
680
+ authority(): string | undefined;
675
681
  headers(): Headers;
676
682
  consume(): IncomingBody;
677
683
  }
678
684
 
679
- export class OutgoingResponse {
680
- constructor(headers: Headers)
681
- statusCode(): StatusCode;
682
- setStatusCode(statusCode: StatusCode): void;
683
- headers(): Headers;
684
- body(): OutgoingBody;
685
- }
686
-
687
685
  export class OutgoingRequest {
688
686
  constructor(headers: Headers)
689
687
  body(): OutgoingBody;
@@ -698,6 +696,12 @@ export class OutgoingRequest {
698
696
  headers(): Headers;
699
697
  }
700
698
 
699
+ export class IncomingResponse {
700
+ status(): StatusCode;
701
+ headers(): Headers;
702
+ consume(): IncomingBody;
703
+ }
704
+
701
705
  export class RequestOptions {
702
706
  constructor()
703
707
  connectTimeout(): Duration | undefined;
@@ -707,7 +711,3 @@ export class RequestOptions {
707
711
  betweenBytesTimeout(): Duration | undefined;
708
712
  setBetweenBytesTimeout(duration: Duration | undefined): void;
709
713
  }
710
-
711
- export class ResponseOutparam {
712
- static set(param: ResponseOutparam, response: Result<OutgoingResponse, ErrorCode>): void;
713
- }
@@ -2,6 +2,11 @@ export namespace WasiIoStreams {
2
2
  /**
3
3
  * Perform a non-blocking read from the stream.
4
4
  *
5
+ * When the source of a `read` is binary data, the bytes from the source
6
+ * are returned verbatim. When the source of a `read` is known to the
7
+ * implementation to be text, bytes containing the UTF-8 encoding of the
8
+ * text are returned.
9
+ *
5
10
  * This function returns a list of bytes containing the read data,
6
11
  * when successful. The returned list will contain up to `len` bytes;
7
12
  * it may return fewer than requested, but not more. The list is
@@ -60,6 +65,12 @@ export namespace WasiIoStreams {
60
65
  /**
61
66
  * Perform a write. This function never blocks.
62
67
  *
68
+ * When the destination of a `write` is binary data, the bytes from
69
+ * `contents` are written verbatim. When the destination of a `write` is
70
+ * known to the implementation to be text, the bytes of `contents` are
71
+ * transcoded from UTF-8 into the encoding of the destination and then
72
+ * written.
73
+ *
63
74
  * Precondition: check-write gave permit of Ok(n) and contents has a
64
75
  * length of less than or equal to n. Otherwise, this function will trap.
65
76
  *
@@ -78,7 +89,7 @@ export namespace WasiIoStreams {
78
89
  * let pollable = this.subscribe();
79
90
  * while !contents.is_empty() {
80
91
  * // Wait for the stream to become writable
81
- * poll-one(pollable);
92
+ * pollable.block();
82
93
  * let Ok(n) = this.check-write(); // eliding error handling
83
94
  * let len = min(n, contents.len());
84
95
  * let (chunk, rest) = contents.split_at(len);
@@ -87,7 +98,7 @@ export namespace WasiIoStreams {
87
98
  * }
88
99
  * this.flush();
89
100
  * // Wait for completion of `flush`
90
- * poll-one(pollable);
101
+ * pollable.block();
91
102
  * // Check for any errors that arose during `flush`
92
103
  * let _ = this.check-write(); // eliding error handling
93
104
  * ```
@@ -123,7 +134,7 @@ export namespace WasiIoStreams {
123
134
  /**
124
135
  * Write zeroes to a stream.
125
136
  *
126
- * this should be used precisely like `write` with the exact same
137
+ * This should be used precisely like `write` with the exact same
127
138
  * preconditions (must use check-write first), but instead of
128
139
  * passing a list of bytes, you simply pass the number of zero-bytes
129
140
  * that should be written.
@@ -141,7 +152,7 @@ export namespace WasiIoStreams {
141
152
  * let pollable = this.subscribe();
142
153
  * while num_zeroes != 0 {
143
154
  * // Wait for the stream to become writable
144
- * poll-one(pollable);
155
+ * pollable.block();
145
156
  * let Ok(n) = this.check-write(); // eliding error handling
146
157
  * let len = min(n, num_zeroes);
147
158
  * this.write-zeroes(len); // eliding error handling
@@ -149,7 +160,7 @@ export namespace WasiIoStreams {
149
160
  * }
150
161
  * this.flush();
151
162
  * // Wait for completion of `flush`
152
- * poll-one(pollable);
163
+ * pollable.block();
153
164
  * // Check for any errors that arose during `flush`
154
165
  * let _ = this.check-write(); // eliding error handling
155
166
  * ```
@@ -76,15 +76,17 @@ export namespace WasiSocketsNetwork {
76
76
  * The remote address is not reachable
77
77
  * ## `"connection-refused"`
78
78
  *
79
- * The connection was forcefully rejected
79
+ * The TCP connection was forcefully rejected
80
80
  * ## `"connection-reset"`
81
81
  *
82
- * The connection was reset.
82
+ * The TCP connection was reset.
83
83
  * ## `"connection-aborted"`
84
84
  *
85
- * A connection was aborted.
85
+ * A TCP connection was aborted.
86
86
  * ## `"datagram-too-large"`
87
87
  *
88
+ * The size of a datagram sent to a UDP socket exceeded the maximum
89
+ * supported size.
88
90
  * ## `"name-unresolvable"`
89
91
  *
90
92
  * Name does not exist or has no suitable associated IP addresses.
@@ -119,13 +121,31 @@ export interface IpAddressIpv6 {
119
121
  val: Ipv6Address,
120
122
  }
121
123
  export interface Ipv4SocketAddress {
124
+ /**
125
+ * sin_port
126
+ */
122
127
  port: number,
128
+ /**
129
+ * sin_addr
130
+ */
123
131
  address: Ipv4Address,
124
132
  }
125
133
  export interface Ipv6SocketAddress {
134
+ /**
135
+ * sin6_port
136
+ */
126
137
  port: number,
138
+ /**
139
+ * sin6_flowinfo
140
+ */
127
141
  flowInfo: number,
142
+ /**
143
+ * sin6_addr
144
+ */
128
145
  address: Ipv6Address,
146
+ /**
147
+ * sin6_scope_id
148
+ */
129
149
  scopeId: number,
130
150
  }
131
151
  export type IpSocketAddress = IpSocketAddressIpv4 | IpSocketAddressIpv6;
@@ -3,9 +3,10 @@ export namespace WasiSocketsTcpCreateSocket {
3
3
  * Create a new TCP socket.
4
4
  *
5
5
  * Similar to `socket(AF_INET or AF_INET6, SOCK_STREAM, IPPROTO_TCP)` in POSIX.
6
+ * On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise.
6
7
  *
7
8
  * This function does not require a network capability handle. This is considered to be safe because
8
- * at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind`/`listen`/`connect`
9
+ * at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind`/`connect`
9
10
  * is called, the socket is effectively an in-memory configuration object, unable to communicate with the outside world.
10
11
  *
11
12
  * All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations.
@@ -6,18 +6,16 @@ export namespace WasiSocketsTcp {
6
6
  * network interface(s) to bind to.
7
7
  * If the TCP/UDP port is zero, the socket will be bound to a random free port.
8
8
  *
9
- * When a socket is not explicitly bound, the first invocation to a listen or connect operation will
10
- * implicitly bind the socket.
9
+ * Bind can be attempted multiple times on the same socket, even with
10
+ * different arguments on each iteration. But never concurrently and
11
+ * only as long as the previous bind failed. Once a bind succeeds, the
12
+ * binding can't be changed anymore.
11
13
  *
12
- * Unlike in POSIX, this function is async. This enables interactive WASI hosts to inject permission prompts.
13
- *
14
- * # Typical `start` errors
14
+ * # Typical errors
15
15
  * - `invalid-argument`: The `local-address` has the wrong address family. (EAFNOSUPPORT, EFAULT on Windows)
16
16
  * - `invalid-argument`: `local-address` is not a unicast address. (EINVAL)
17
- * - `invalid-argument`: `local-address` is an IPv4-mapped IPv6 address, but the socket has `ipv6-only` enabled. (EINVAL)
17
+ * - `invalid-argument`: `local-address` is an IPv4-mapped IPv6 address. (EINVAL)
18
18
  * - `invalid-state`: The socket is already bound. (EINVAL)
19
- *
20
- * # Typical `finish` errors
21
19
  * - `address-in-use`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows)
22
20
  * - `address-in-use`: Address is already in use. (EADDRINUSE)
23
21
  * - `address-not-bindable`: `local-address` is not an address that the `network` can bind to. (EADDRNOTAVAIL)
@@ -26,8 +24,14 @@ export namespace WasiSocketsTcp {
26
24
  *
27
25
  * # Implementors note
28
26
  * When binding to a non-zero port, this bind operation shouldn't be affected by the TIME_WAIT
29
- * state of a recently closed socket on the same local address (i.e. the SO_REUSEADDR socket
30
- * option should be set implicitly on platforms that require it).
27
+ * state of a recently closed socket on the same local address. In practice this means that the SO_REUSEADDR
28
+ * socket option should be set implicitly on all platforms, except on Windows where this is the default behavior
29
+ * and SO_REUSEADDR performs something different entirely.
30
+ *
31
+ * Unlike in POSIX, in WASI the bind operation is async. This enables
32
+ * interactive WASI hosts to inject permission prompts. Runtimes that
33
+ * don't want to make use of this ability can simply call the native
34
+ * `bind` as part of either `start-bind` or `finish-bind`.
31
35
  *
32
36
  * # References
33
37
  * - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html>
@@ -40,39 +44,40 @@ export namespace WasiSocketsTcp {
40
44
  * Connect to a remote endpoint.
41
45
  *
42
46
  * On success:
43
- * - the socket is transitioned into the Connection state
47
+ * - the socket is transitioned into the `connection` state.
44
48
  * - a pair of streams is returned that can be used to read & write to the connection
45
49
  *
46
- * POSIX mentions:
47
- * > If connect() fails, the state of the socket is unspecified. Conforming applications should
48
- * > close the file descriptor and create a new socket before attempting to reconnect.
49
- *
50
- * WASI prescribes the following behavior:
51
- * - If `connect` fails because an input/state validation error, the socket should remain usable.
52
- * - If a connection was actually attempted but failed, the socket should become unusable for further network communication.
53
- * Besides `drop`, any method after such a failure may return an error.
50
+ * After a failed connection attempt, the socket will be in the `closed`
51
+ * state and the only valid action left is to `drop` the socket. A single
52
+ * socket can not be used to connect more than once.
54
53
  *
55
- * # Typical `start` errors
54
+ * # Typical errors
56
55
  * - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT)
57
56
  * - `invalid-argument`: `remote-address` is not a unicast address. (EINVAL, ENETUNREACH on Linux, EAFNOSUPPORT on MacOS)
58
- * - `invalid-argument`: `remote-address` is an IPv4-mapped IPv6 address, but the socket has `ipv6-only` enabled. (EINVAL, EADDRNOTAVAIL on Illumos)
59
- * - `invalid-argument`: `remote-address` is a non-IPv4-mapped IPv6 address, but the socket was bound to a specific IPv4-mapped IPv6 address. (or vice versa)
57
+ * - `invalid-argument`: `remote-address` is an IPv4-mapped IPv6 address. (EINVAL, EADDRNOTAVAIL on Illumos)
60
58
  * - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EADDRNOTAVAIL on Windows)
61
59
  * - `invalid-argument`: The port in `remote-address` is set to 0. (EADDRNOTAVAIL on Windows)
62
60
  * - `invalid-argument`: The socket is already attached to a different network. The `network` passed to `connect` must be identical to the one passed to `bind`.
63
- * - `invalid-state`: The socket is already in the Connection state. (EISCONN)
64
- * - `invalid-state`: The socket is already in the Listener state. (EOPNOTSUPP, EINVAL on Windows)
65
- *
66
- * # Typical `finish` errors
61
+ * - `invalid-state`: The socket is already in the `connected` state. (EISCONN)
62
+ * - `invalid-state`: The socket is already in the `listening` state. (EOPNOTSUPP, EINVAL on Windows)
67
63
  * - `timeout`: Connection timed out. (ETIMEDOUT)
68
64
  * - `connection-refused`: The connection was forcefully rejected. (ECONNREFUSED)
69
65
  * - `connection-reset`: The connection was reset. (ECONNRESET)
70
66
  * - `connection-aborted`: The connection was aborted. (ECONNABORTED)
71
67
  * - `remote-unreachable`: The remote address is not reachable. (EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET)
72
68
  * - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD)
73
- * - `not-in-progress`: A `connect` operation is not in progress.
69
+ * - `not-in-progress`: A connect operation is not in progress.
74
70
  * - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN)
75
71
  *
72
+ * # Implementors note
73
+ * The POSIX equivalent of `start-connect` is the regular `connect` syscall.
74
+ * Because all WASI sockets are non-blocking this is expected to return
75
+ * EINPROGRESS, which should be translated to `ok()` in WASI.
76
+ *
77
+ * The POSIX equivalent of `finish-connect` is a `poll` for event `POLLOUT`
78
+ * with a timeout of 0 on the socket descriptor. Followed by a check for
79
+ * the `SO_ERROR` socket option, in case the poll signaled readiness.
80
+ *
76
81
  * # References
77
82
  * - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html>
78
83
  * - <https://man7.org/linux/man-pages/man2/connect.2.html>
@@ -82,22 +87,24 @@ export namespace WasiSocketsTcp {
82
87
  /**
83
88
  * Start listening for new connections.
84
89
  *
85
- * Transitions the socket into the Listener state.
90
+ * Transitions the socket into the `listening` state.
86
91
  *
87
- * Unlike POSIX:
88
- * - this function is async. This enables interactive WASI hosts to inject permission prompts.
89
- * - the socket must already be explicitly bound.
92
+ * Unlike POSIX, the socket must already be explicitly bound.
90
93
  *
91
- * # Typical `start` errors
94
+ * # Typical errors
92
95
  * - `invalid-state`: The socket is not bound to any local address. (EDESTADDRREQ)
93
- * - `invalid-state`: The socket is already in the Connection state. (EISCONN, EINVAL on BSD)
94
- * - `invalid-state`: The socket is already in the Listener state.
95
- *
96
- * # Typical `finish` errors
96
+ * - `invalid-state`: The socket is already in the `connected` state. (EISCONN, EINVAL on BSD)
97
+ * - `invalid-state`: The socket is already in the `listening` state.
97
98
  * - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE)
98
- * - `not-in-progress`: A `listen` operation is not in progress.
99
+ * - `not-in-progress`: A listen operation is not in progress.
99
100
  * - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN)
100
101
  *
102
+ * # Implementors note
103
+ * Unlike in POSIX, in WASI the listen operation is async. This enables
104
+ * interactive WASI hosts to inject permission prompts. Runtimes that
105
+ * don't want to make use of this ability can simply call the native
106
+ * `listen` as part of either `start-listen` or `finish-listen`.
107
+ *
101
108
  * # References
102
109
  * - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html>
103
110
  * - <https://man7.org/linux/man-pages/man2/listen.2.html>
@@ -107,9 +114,8 @@ export namespace WasiSocketsTcp {
107
114
  /**
108
115
  * Accept a new client socket.
109
116
  *
110
- * The returned socket is bound and in the Connection state. The following properties are inherited from the listener socket:
117
+ * The returned socket is bound and in the `connected` state. The following properties are inherited from the listener socket:
111
118
  * - `address-family`
112
- * - `ipv6-only`
113
119
  * - `keep-alive-enabled`
114
120
  * - `keep-alive-idle-time`
115
121
  * - `keep-alive-interval`
@@ -122,7 +128,7 @@ export namespace WasiSocketsTcp {
122
128
  * a pair of streams that can be used to read & write to the connection.
123
129
  *
124
130
  * # Typical errors
125
- * - `invalid-state`: Socket is not in the Listener state. (EINVAL)
131
+ * - `invalid-state`: Socket is not in the `listening` state. (EINVAL)
126
132
  * - `would-block`: No pending connections at the moment. (EWOULDBLOCK, EAGAIN)
127
133
  * - `connection-aborted`: An incoming connection was pending, but was terminated by the client before this listener could accept it. (ECONNABORTED)
128
134
  * - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE)
@@ -164,7 +170,7 @@ export namespace WasiSocketsTcp {
164
170
  * - <https://man.freebsd.org/cgi/man.cgi?query=getpeername&sektion=2&n=1>
165
171
  */
166
172
  /**
167
- * Whether the socket is listening for new connections.
173
+ * Whether the socket is in the `listening` state.
168
174
  *
169
175
  * Equivalent to the SO_ACCEPTCONN socket option.
170
176
  */
@@ -173,16 +179,6 @@ export namespace WasiSocketsTcp {
173
179
  *
174
180
  * Equivalent to the SO_DOMAIN socket option.
175
181
  */
176
- /**
177
- * Whether IPv4 compatibility (dual-stack) mode is disabled or not.
178
- *
179
- * Equivalent to the IPV6_V6ONLY socket option.
180
- *
181
- * # Typical errors
182
- * - `invalid-state`: (set) The socket is already bound.
183
- * - `not-supported`: (get/set) `this` socket is an IPv4 socket.
184
- * - `not-supported`: (set) Host does not support dual-stack sockets. (Implementations are not required to.)
185
- */
186
182
  /**
187
183
  * Hints the desired listen queue size. Implementations are free to ignore this.
188
184
  *
@@ -192,7 +188,7 @@ export namespace WasiSocketsTcp {
192
188
  * # Typical errors
193
189
  * - `not-supported`: (set) The platform does not support changing the backlog size after the initial listen.
194
190
  * - `invalid-argument`: (set) The provided value was 0.
195
- * - `invalid-state`: (set) The socket is already in the Connection state.
191
+ * - `invalid-state`: (set) The socket is in the `connect-in-progress` or `connected` state.
196
192
  */
197
193
  /**
198
194
  * Enables or disables keepalive.
@@ -248,8 +244,6 @@ export namespace WasiSocketsTcp {
248
244
  *
249
245
  * # Typical errors
250
246
  * - `invalid-argument`: (set) The TTL value must be 1 or higher.
251
- * - `invalid-state`: (set) The socket is already in the Connection state.
252
- * - `invalid-state`: (set) The socket is already in the Listener state.
253
247
  */
254
248
  /**
255
249
  * The kernel buffer space reserved for sends/receives on this socket.
@@ -262,11 +256,22 @@ export namespace WasiSocketsTcp {
262
256
  *
263
257
  * # Typical errors
264
258
  * - `invalid-argument`: (set) The provided value was 0.
265
- * - `invalid-state`: (set) The socket is already in the Connection state.
266
- * - `invalid-state`: (set) The socket is already in the Listener state.
267
259
  */
268
260
  /**
269
- * Create a `pollable` which will resolve once the socket is ready for I/O.
261
+ * Create a `pollable` which can be used to poll for, or block on,
262
+ * completion of any of the asynchronous operations of this socket.
263
+ *
264
+ * When `finish-bind`, `finish-listen`, `finish-connect` or `accept`
265
+ * return `error(would-block)`, this pollable can be used to wait for
266
+ * their success or failure, after which the method can be retried.
267
+ *
268
+ * The pollable is not limited to the async operation that happens to be
269
+ * in progress at the time of calling `subscribe` (if any). Theoretically,
270
+ * `subscribe` only has to be called once per socket and can then be
271
+ * (re)used for the remainder of the socket's lifetime.
272
+ *
273
+ * See <https://github.com/WebAssembly/wasi-sockets/TcpSocketOperationalSemantics.md#Pollable-readiness>
274
+ * for a more information.
270
275
  *
271
276
  * Note: this function is here for WASI Preview2 only.
272
277
  * It's planned to be removed when `future` is natively supported in Preview3.
@@ -274,17 +279,21 @@ export namespace WasiSocketsTcp {
274
279
  /**
275
280
  * Initiate a graceful shutdown.
276
281
  *
277
- * - receive: the socket is not expecting to receive any more data from the peer. All subsequent read
278
- * operations on the `input-stream` associated with this socket will return an End Of Stream indication.
279
- * Any data still in the receive queue at time of calling `shutdown` will be discarded.
280
- * - send: the socket is not expecting to send any more data to the peer. All subsequent write
281
- * operations on the `output-stream` associated with this socket will return an error.
282
- * - both: same effect as receive & send combined.
282
+ * - `receive`: The socket is not expecting to receive any data from
283
+ * the peer. The `input-stream` associated with this socket will be
284
+ * closed. Any data still in the receive queue at time of calling
285
+ * this method will be discarded.
286
+ * - `send`: The socket has no more data to send to the peer. The `output-stream`
287
+ * associated with this socket will be closed and a FIN packet will be sent.
288
+ * - `both`: Same effect as `receive` & `send` combined.
289
+ *
290
+ * This function is idempotent. Shutting a down a direction more than once
291
+ * has no effect and returns `ok`.
283
292
  *
284
293
  * The shutdown function does not close (drop) the socket.
285
294
  *
286
295
  * # Typical errors
287
- * - `invalid-state`: The socket is not in the Connection state. (ENOTCONN)
296
+ * - `invalid-state`: The socket is not in the `connected` state. (ENOTCONN)
288
297
  *
289
298
  * # References
290
299
  * - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html>
@@ -336,8 +345,6 @@ export class TcpSocket {
336
345
  remoteAddress(): IpSocketAddress;
337
346
  isListening(): boolean;
338
347
  addressFamily(): IpAddressFamily;
339
- ipv6Only(): boolean;
340
- setIpv6Only(value: boolean): void;
341
348
  setListenBacklogSize(value: bigint): void;
342
349
  keepAliveEnabled(): boolean;
343
350
  setKeepAliveEnabled(value: boolean): void;
@@ -3,6 +3,7 @@ export namespace WasiSocketsUdpCreateSocket {
3
3
  * Create a new UDP socket.
4
4
  *
5
5
  * Similar to `socket(AF_INET or AF_INET6, SOCK_DGRAM, IPPROTO_UDP)` in POSIX.
6
+ * On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise.
6
7
  *
7
8
  * This function does not require a network capability handle. This is considered to be safe because
8
9
  * at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind` is called,
@@ -6,19 +6,21 @@ export namespace WasiSocketsUdp {
6
6
  * network interface(s) to bind to.
7
7
  * If the port is zero, the socket will be bound to a random free port.
8
8
  *
9
- * Unlike in POSIX, this function is async. This enables interactive WASI hosts to inject permission prompts.
10
- *
11
- * # Typical `start` errors
9
+ * # Typical errors
12
10
  * - `invalid-argument`: The `local-address` has the wrong address family. (EAFNOSUPPORT, EFAULT on Windows)
13
11
  * - `invalid-state`: The socket is already bound. (EINVAL)
14
- *
15
- * # Typical `finish` errors
16
12
  * - `address-in-use`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows)
17
13
  * - `address-in-use`: Address is already in use. (EADDRINUSE)
18
14
  * - `address-not-bindable`: `local-address` is not an address that the `network` can bind to. (EADDRNOTAVAIL)
19
15
  * - `not-in-progress`: A `bind` operation is not in progress.
20
16
  * - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN)
21
17
  *
18
+ * # Implementors note
19
+ * Unlike in POSIX, in WASI the bind operation is async. This enables
20
+ * interactive WASI hosts to inject permission prompts. Runtimes that
21
+ * don't want to make use of this ability can simply call the native
22
+ * `bind` as part of either `start-bind` or `finish-bind`.
23
+ *
22
24
  * # References
23
25
  * - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html>
24
26
  * - <https://man7.org/linux/man-pages/man2/bind.2.html>
@@ -55,7 +57,6 @@ export namespace WasiSocketsUdp {
55
57
  *
56
58
  * # Typical errors
57
59
  * - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT)
58
- * - `invalid-argument`: `remote-address` is a non-IPv4-mapped IPv6 address, but the socket was bound to a specific IPv4-mapped IPv6 address. (or vice versa)
59
60
  * - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL)
60
61
  * - `invalid-argument`: The port in `remote-address` is set to 0. (EDESTADDRREQ, EADDRNOTAVAIL)
61
62
  * - `invalid-state`: The socket is not bound.
@@ -104,16 +105,6 @@ export namespace WasiSocketsUdp {
104
105
  *
105
106
  * Equivalent to the SO_DOMAIN socket option.
106
107
  */
107
- /**
108
- * Whether IPv4 compatibility (dual-stack) mode is disabled or not.
109
- *
110
- * Equivalent to the IPV6_V6ONLY socket option.
111
- *
112
- * # Typical errors
113
- * - `not-supported`: (get/set) `this` socket is an IPv4 socket.
114
- * - `invalid-state`: (set) The socket is already bound.
115
- * - `not-supported`: (set) Host does not support dual-stack sockets. (Implementations are not required to.)
116
- */
117
108
  /**
118
109
  * Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options.
119
110
  *
@@ -204,7 +195,6 @@ export namespace WasiSocketsUdp {
204
195
  *
205
196
  * # Typical errors
206
197
  * - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT)
207
- * - `invalid-argument`: `remote-address` is a non-IPv4-mapped IPv6 address, but the socket was bound to a specific IPv4-mapped IPv6 address. (or vice versa)
208
198
  * - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL)
209
199
  * - `invalid-argument`: The port in `remote-address` is set to 0. (EDESTADDRREQ, EADDRNOTAVAIL)
210
200
  * - `invalid-argument`: The socket is in "connected" mode and `remote-address` is `some` value that does not match the address passed to `stream`. (EISCONN)
@@ -279,6 +269,17 @@ export namespace WasiSocketsUdp {
279
269
  remoteAddress?: IpSocketAddress,
280
270
  }
281
271
 
272
+ export class IncomingDatagramStream {
273
+ receive(maxResults: bigint): IncomingDatagram[];
274
+ subscribe(): Pollable;
275
+ }
276
+
277
+ export class OutgoingDatagramStream {
278
+ checkSend(): bigint;
279
+ send(datagrams: OutgoingDatagram[]): bigint;
280
+ subscribe(): Pollable;
281
+ }
282
+
282
283
  export class UdpSocket {
283
284
  startBind(network: Network, localAddress: IpSocketAddress): void;
284
285
  finishBind(): void;
@@ -286,8 +287,6 @@ export namespace WasiSocketsUdp {
286
287
  localAddress(): IpSocketAddress;
287
288
  remoteAddress(): IpSocketAddress;
288
289
  addressFamily(): IpAddressFamily;
289
- ipv6Only(): boolean;
290
- setIpv6Only(value: boolean): void;
291
290
  unicastHopLimit(): number;
292
291
  setUnicastHopLimit(value: number): void;
293
292
  receiveBufferSize(): bigint;
@@ -296,15 +295,4 @@ export namespace WasiSocketsUdp {
296
295
  setSendBufferSize(value: bigint): void;
297
296
  subscribe(): Pollable;
298
297
  }
299
-
300
- export class IncomingDatagramStream {
301
- receive(maxResults: bigint): IncomingDatagram[];
302
- subscribe(): Pollable;
303
- }
304
-
305
- export class OutgoingDatagramStream {
306
- checkSend(): bigint;
307
- send(datagrams: OutgoingDatagram[]): bigint;
308
- subscribe(): Pollable;
309
- }
310
298
 
package/types/io.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import type { WasiIoError } from './interfaces/wasi-io-error.d.ts';
2
+ import type { WasiIoPoll } from './interfaces/wasi-io-poll.d.ts';
3
+ import type { WasiIoStreams } from './interfaces/wasi-io-streams.d.ts';
4
+
5
+ export const error: typeof WasiIoError;
6
+ export const poll: typeof WasiIoPoll;
7
+ export const streams: typeof WasiIoStreams;
@@ -0,0 +1,7 @@
1
+ import type { WasiRandomInsecureSeed } from './interfaces/wasi-random-insecure-seed.d.ts';
2
+ import type { WasiRandomInsecure } from './interfaces/wasi-random-insecure.d.ts';
3
+ import type { WasiRandomRandom } from './interfaces/wasi-random-random.d.ts';
4
+
5
+ export const insecureSeed: typeof WasiRandomInsecureSeed;
6
+ export const insecure: typeof WasiRandomInsecure;
7
+ export const random: typeof WasiRandomRandom;
@@ -0,0 +1,15 @@
1
+ import type { WasiSocketsInstanceNetwork } from './interfaces/wasi-sockets-instance-network.d.ts';
2
+ import type { WasiSocketsIpNameLookup } from './interfaces/wasi-sockets-ip-name-lookup.d.ts';
3
+ import type { WasiSocketsNetwork } from './interfaces/wasi-sockets-network.d.ts';
4
+ import type { WasiSocketsTcpCreateSocket } from './interfaces/wasi-sockets-tcp-create-socket.d.ts';
5
+ import type { WasiSocketsTcp } from './interfaces/wasi-sockets-tcp.d.ts';
6
+ import type { WasiSocketsUdpCreateSocket } from './interfaces/wasi-sockets-udp-create-socket.d.ts';
7
+ import type { WasiSocketsUdp } from './interfaces/wasi-sockets-udp.d.ts';
8
+
9
+ export const instanceNetwork: typeof WasiSocketsInstanceNetwork;
10
+ export const ipNameLookup: typeof WasiSocketsIpNameLookup;
11
+ export const network: typeof WasiSocketsNetwork;
12
+ export const tcpCreateSocket: typeof WasiSocketsTcpCreateSocket;
13
+ export const tcp: typeof WasiSocketsTcp;
14
+ export const udpCreateSocket: typeof WasiSocketsUdpCreateSocket;
15
+ export const udp: typeof WasiSocketsUdp;