wasm-platform-kit 0.0.0-stage → 0.2.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/LICENSE +21 -0
- package/README.md +224 -2
- package/assets/wasi/LICENSE +220 -0
- package/assets/wasi/cli.d.ts +43 -0
- package/assets/wasi/cli.js +147 -0
- package/assets/wasi/clocks.d.ts +3 -0
- package/assets/wasi/clocks.js +55 -0
- package/assets/wasi/common.d.ts +5 -0
- package/assets/wasi/common.js +16 -0
- package/assets/wasi/config.d.ts +2 -0
- package/assets/wasi/config.js +7 -0
- package/assets/wasi/environment.d.ts +5 -0
- package/assets/wasi/environment.js +24 -0
- package/assets/wasi/filesystem.d.ts +117 -0
- package/assets/wasi/filesystem.js +341 -0
- package/assets/wasi/helpers/cli.d.ts +7 -0
- package/assets/wasi/helpers/cli.js +25 -0
- package/assets/wasi/helpers/filesystem.d.ts +6 -0
- package/assets/wasi/helpers/filesystem.js +10 -0
- package/assets/wasi/http.d.ts +13 -0
- package/assets/wasi/http.js +953 -0
- package/assets/wasi/in-memory-filesystem.d.ts +38 -0
- package/assets/wasi/in-memory-filesystem.js +620 -0
- package/assets/wasi/in-memory-http.d.ts +8 -0
- package/assets/wasi/in-memory-http.js +11 -0
- package/assets/wasi/in-memory-sockets.d.ts +34 -0
- package/assets/wasi/in-memory-sockets.js +294 -0
- package/assets/wasi/index.d.ts +7 -0
- package/assets/wasi/index.js +7 -0
- package/assets/wasi/io.d.ts +67 -0
- package/assets/wasi/io.js +366 -0
- package/assets/wasi/opfs-filesystem.d.ts +52 -0
- package/assets/wasi/opfs-filesystem.js +262 -0
- package/assets/wasi/random.d.ts +4 -0
- package/assets/wasi/random.js +51 -0
- package/assets/wasi/sockets.d.ts +9 -0
- package/assets/wasi/sockets.js +85 -0
- package/browser.mjs +209 -0
- package/client.mjs +138 -0
- package/index.d.ts +199 -0
- package/install.d.ts +22 -0
- package/install.mjs +176 -0
- package/native-registration.mjs +70 -0
- package/node.mjs +332 -0
- package/package.json +66 -4
- package/policy.mjs +433 -0
- package/worker.mjs +389 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { TcpSocketsShim, UdpSocketsShim } from "../../types/instantiation.js";
|
|
2
|
+
import type { IpSocketAddress } from "../../types/interfaces/wasi-sockets-network.js";
|
|
3
|
+
import type { InputStream, OutputStream } from "../../types/interfaces/wasi-io-streams.js";
|
|
4
|
+
/** The browser-side endpoint of an in-memory TCP connection. */
|
|
5
|
+
export declare class InMemoryTcpClient {
|
|
6
|
+
#private;
|
|
7
|
+
write(bytes: Uint8Array): void;
|
|
8
|
+
read(length?: bigint): Uint8Array;
|
|
9
|
+
_serverStreams(): readonly [InputStream, OutputStream];
|
|
10
|
+
}
|
|
11
|
+
/** Deterministic, process-local TCP namespaces with a browser-side client API. */
|
|
12
|
+
export declare class InMemoryTcpSockets implements TcpSocketsShim {
|
|
13
|
+
#private;
|
|
14
|
+
readonly tcp: TcpSocketsShim["tcp"];
|
|
15
|
+
readonly tcpCreateSocket: TcpSocketsShim["tcpCreateSocket"];
|
|
16
|
+
constructor();
|
|
17
|
+
connect(serverAddress: IpSocketAddress): InMemoryTcpClient;
|
|
18
|
+
}
|
|
19
|
+
/** The browser-side endpoint of an in-memory UDP socket. */
|
|
20
|
+
export declare class InMemoryUdpClient {
|
|
21
|
+
#private;
|
|
22
|
+
constructor(send: (bytes: Uint8Array, serverAddress: IpSocketAddress) => void);
|
|
23
|
+
send(bytes: Uint8Array, serverAddress: IpSocketAddress): void;
|
|
24
|
+
read(): Uint8Array;
|
|
25
|
+
_receive(bytes: Uint8Array): void;
|
|
26
|
+
}
|
|
27
|
+
/** Deterministic, process-local UDP namespaces with a browser-side client API. */
|
|
28
|
+
export declare class InMemoryUdpSockets implements UdpSocketsShim {
|
|
29
|
+
#private;
|
|
30
|
+
readonly udp: UdpSocketsShim["udp"];
|
|
31
|
+
readonly udpCreateSocket: UdpSocketsShim["udpCreateSocket"];
|
|
32
|
+
constructor();
|
|
33
|
+
createClient(localAddress: IpSocketAddress): InMemoryUdpClient;
|
|
34
|
+
}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { checkedU64AsNumber } from "./common.js";
|
|
2
|
+
import { inputStreamCreate, outputStreamCreate, pollableCreate } from "./io.js";
|
|
3
|
+
const symbolDispose = Symbol.dispose || Symbol.for("dispose");
|
|
4
|
+
const unsupported = () => {
|
|
5
|
+
throw "not-supported";
|
|
6
|
+
};
|
|
7
|
+
function addressKey(address) {
|
|
8
|
+
return `${address.tag}:${address.val.address.join(".")}:${address.val.port}`;
|
|
9
|
+
}
|
|
10
|
+
function takeBytes(chunks, length) {
|
|
11
|
+
const chunk = chunks.shift();
|
|
12
|
+
if (!chunk) {
|
|
13
|
+
throw { tag: "closed" };
|
|
14
|
+
}
|
|
15
|
+
const requested = checkedU64AsNumber(length, "length");
|
|
16
|
+
if (chunk.byteLength <= requested) {
|
|
17
|
+
return chunk;
|
|
18
|
+
}
|
|
19
|
+
chunks.unshift(chunk.subarray(requested));
|
|
20
|
+
return chunk.subarray(0, requested);
|
|
21
|
+
}
|
|
22
|
+
/** The browser-side endpoint of an in-memory TCP connection. */
|
|
23
|
+
export class InMemoryTcpClient {
|
|
24
|
+
#toServer = [];
|
|
25
|
+
#fromServer = [];
|
|
26
|
+
write(bytes) {
|
|
27
|
+
this.#toServer.push(new Uint8Array(bytes));
|
|
28
|
+
}
|
|
29
|
+
read(length = 4096n) {
|
|
30
|
+
return takeBytes(this.#fromServer, length);
|
|
31
|
+
}
|
|
32
|
+
_serverStreams() {
|
|
33
|
+
return [
|
|
34
|
+
inputStreamCreate({ blockingRead: (length) => takeBytes(this.#toServer, length) }),
|
|
35
|
+
outputStreamCreate({
|
|
36
|
+
write: (bytes) => this.#fromServer.push(new Uint8Array(bytes)),
|
|
37
|
+
}),
|
|
38
|
+
];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** Deterministic, process-local TCP namespaces with a browser-side client API. */
|
|
42
|
+
export class InMemoryTcpSockets {
|
|
43
|
+
#pending = new Map();
|
|
44
|
+
tcp;
|
|
45
|
+
tcpCreateSocket;
|
|
46
|
+
constructor() {
|
|
47
|
+
const pending = this.#pending;
|
|
48
|
+
class TcpSocket {
|
|
49
|
+
#family;
|
|
50
|
+
#localAddress;
|
|
51
|
+
#remoteAddress;
|
|
52
|
+
#listening = false;
|
|
53
|
+
constructor(family) {
|
|
54
|
+
this.#family = family;
|
|
55
|
+
}
|
|
56
|
+
startBind(_network, localAddress) {
|
|
57
|
+
this.#localAddress = localAddress;
|
|
58
|
+
}
|
|
59
|
+
finishBind() {
|
|
60
|
+
if (!this.#localAddress) {
|
|
61
|
+
throw "not-in-progress";
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
startConnect = unsupported;
|
|
65
|
+
finishConnect = unsupported;
|
|
66
|
+
startListen() {
|
|
67
|
+
if (!this.#localAddress) {
|
|
68
|
+
throw "invalid-state";
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
finishListen() {
|
|
72
|
+
this.#listening = true;
|
|
73
|
+
}
|
|
74
|
+
accept() {
|
|
75
|
+
if (!this.#listening || !this.#localAddress) {
|
|
76
|
+
throw "invalid-state";
|
|
77
|
+
}
|
|
78
|
+
const client = pending.get(addressKey(this.#localAddress))?.shift();
|
|
79
|
+
if (!client) {
|
|
80
|
+
throw "would-block";
|
|
81
|
+
}
|
|
82
|
+
const connected = new TcpSocket(this.#family);
|
|
83
|
+
connected.#localAddress = this.#localAddress;
|
|
84
|
+
const [input, output] = client._serverStreams();
|
|
85
|
+
return [connected, input, output];
|
|
86
|
+
}
|
|
87
|
+
localAddress() {
|
|
88
|
+
if (!this.#localAddress) {
|
|
89
|
+
throw "invalid-state";
|
|
90
|
+
}
|
|
91
|
+
return this.#localAddress;
|
|
92
|
+
}
|
|
93
|
+
remoteAddress() {
|
|
94
|
+
if (!this.#remoteAddress) {
|
|
95
|
+
throw "invalid-state";
|
|
96
|
+
}
|
|
97
|
+
return this.#remoteAddress;
|
|
98
|
+
}
|
|
99
|
+
isListening() {
|
|
100
|
+
return this.#listening;
|
|
101
|
+
}
|
|
102
|
+
addressFamily() {
|
|
103
|
+
return this.#family;
|
|
104
|
+
}
|
|
105
|
+
setListenBacklogSize = unsupported;
|
|
106
|
+
keepAliveEnabled = unsupported;
|
|
107
|
+
setKeepAliveEnabled = unsupported;
|
|
108
|
+
keepAliveIdleTime = unsupported;
|
|
109
|
+
setKeepAliveIdleTime = unsupported;
|
|
110
|
+
keepAliveInterval = unsupported;
|
|
111
|
+
setKeepAliveInterval = unsupported;
|
|
112
|
+
keepAliveCount = unsupported;
|
|
113
|
+
setKeepAliveCount = unsupported;
|
|
114
|
+
hopLimit = unsupported;
|
|
115
|
+
setHopLimit = unsupported;
|
|
116
|
+
receiveBufferSize = unsupported;
|
|
117
|
+
setReceiveBufferSize = unsupported;
|
|
118
|
+
sendBufferSize = unsupported;
|
|
119
|
+
setSendBufferSize = unsupported;
|
|
120
|
+
subscribe() {
|
|
121
|
+
return pollableCreate();
|
|
122
|
+
}
|
|
123
|
+
shutdown() { }
|
|
124
|
+
[symbolDispose]() { }
|
|
125
|
+
}
|
|
126
|
+
this.tcp = { TcpSocket };
|
|
127
|
+
this.tcpCreateSocket = {
|
|
128
|
+
createTcpSocket: (family) => new TcpSocket(family),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
connect(serverAddress) {
|
|
132
|
+
const client = new InMemoryTcpClient();
|
|
133
|
+
const key = addressKey(serverAddress);
|
|
134
|
+
const clients = this.#pending.get(key);
|
|
135
|
+
if (clients) {
|
|
136
|
+
clients.push(client);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
this.#pending.set(key, [client]);
|
|
140
|
+
}
|
|
141
|
+
return client;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/** The browser-side endpoint of an in-memory UDP socket. */
|
|
145
|
+
export class InMemoryUdpClient {
|
|
146
|
+
#send;
|
|
147
|
+
#received = [];
|
|
148
|
+
constructor(send) {
|
|
149
|
+
this.#send = send;
|
|
150
|
+
}
|
|
151
|
+
send(bytes, serverAddress) {
|
|
152
|
+
this.#send(bytes, serverAddress);
|
|
153
|
+
}
|
|
154
|
+
read() {
|
|
155
|
+
return takeBytes(this.#received, 65535n);
|
|
156
|
+
}
|
|
157
|
+
_receive(bytes) {
|
|
158
|
+
this.#received.push(new Uint8Array(bytes));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/** Deterministic, process-local UDP namespaces with a browser-side client API. */
|
|
162
|
+
export class InMemoryUdpSockets {
|
|
163
|
+
#datagrams = new Map();
|
|
164
|
+
#clients = new Map();
|
|
165
|
+
udp;
|
|
166
|
+
udpCreateSocket;
|
|
167
|
+
constructor() {
|
|
168
|
+
const datagrams = this.#datagrams;
|
|
169
|
+
const clients = this.#clients;
|
|
170
|
+
class IncomingDatagramStream {
|
|
171
|
+
queue;
|
|
172
|
+
constructor(queue) {
|
|
173
|
+
this.queue = queue;
|
|
174
|
+
}
|
|
175
|
+
receive(maxResults) {
|
|
176
|
+
return this.queue.splice(0, checkedU64AsNumber(maxResults, "max results"));
|
|
177
|
+
}
|
|
178
|
+
subscribe() {
|
|
179
|
+
return pollableCreate();
|
|
180
|
+
}
|
|
181
|
+
[symbolDispose]() { }
|
|
182
|
+
}
|
|
183
|
+
class OutgoingDatagramStream {
|
|
184
|
+
remoteAddress;
|
|
185
|
+
#permit = 0;
|
|
186
|
+
constructor(remoteAddress) {
|
|
187
|
+
this.remoteAddress = remoteAddress;
|
|
188
|
+
}
|
|
189
|
+
checkSend() {
|
|
190
|
+
this.#permit = 1_024;
|
|
191
|
+
return 1024n;
|
|
192
|
+
}
|
|
193
|
+
send(outgoing) {
|
|
194
|
+
if (outgoing.length > this.#permit) {
|
|
195
|
+
throw new TypeError("datagram count exceeds the permit returned by checkSend");
|
|
196
|
+
}
|
|
197
|
+
this.#permit -= outgoing.length;
|
|
198
|
+
for (const datagram of outgoing) {
|
|
199
|
+
const destination = datagram.remoteAddress ?? this.remoteAddress;
|
|
200
|
+
if (!destination) {
|
|
201
|
+
throw "invalid-argument";
|
|
202
|
+
}
|
|
203
|
+
const client = clients.get(addressKey(destination));
|
|
204
|
+
if (!client) {
|
|
205
|
+
throw "remote-unreachable";
|
|
206
|
+
}
|
|
207
|
+
client._receive(datagram.data);
|
|
208
|
+
}
|
|
209
|
+
return BigInt(outgoing.length);
|
|
210
|
+
}
|
|
211
|
+
subscribe() {
|
|
212
|
+
return pollableCreate();
|
|
213
|
+
}
|
|
214
|
+
[symbolDispose]() { }
|
|
215
|
+
}
|
|
216
|
+
class UdpSocket {
|
|
217
|
+
#family;
|
|
218
|
+
#localAddress;
|
|
219
|
+
#remoteAddress;
|
|
220
|
+
constructor(family) {
|
|
221
|
+
this.#family = family;
|
|
222
|
+
}
|
|
223
|
+
startBind(_network, localAddress) {
|
|
224
|
+
this.#localAddress = localAddress;
|
|
225
|
+
}
|
|
226
|
+
finishBind() {
|
|
227
|
+
if (!this.#localAddress) {
|
|
228
|
+
throw "not-in-progress";
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
stream(remoteAddress) {
|
|
232
|
+
if (!this.#localAddress) {
|
|
233
|
+
throw "invalid-state";
|
|
234
|
+
}
|
|
235
|
+
this.#remoteAddress = remoteAddress;
|
|
236
|
+
const key = addressKey(this.#localAddress);
|
|
237
|
+
let queue = datagrams.get(key);
|
|
238
|
+
if (!queue) {
|
|
239
|
+
queue = [];
|
|
240
|
+
datagrams.set(key, queue);
|
|
241
|
+
}
|
|
242
|
+
return [
|
|
243
|
+
new IncomingDatagramStream(queue),
|
|
244
|
+
new OutgoingDatagramStream(remoteAddress),
|
|
245
|
+
];
|
|
246
|
+
}
|
|
247
|
+
localAddress() {
|
|
248
|
+
if (!this.#localAddress) {
|
|
249
|
+
throw "invalid-state";
|
|
250
|
+
}
|
|
251
|
+
return this.#localAddress;
|
|
252
|
+
}
|
|
253
|
+
remoteAddress() {
|
|
254
|
+
return this.#remoteAddress;
|
|
255
|
+
}
|
|
256
|
+
addressFamily() {
|
|
257
|
+
return this.#family;
|
|
258
|
+
}
|
|
259
|
+
unicastHopLimit = unsupported;
|
|
260
|
+
setUnicastHopLimit = unsupported;
|
|
261
|
+
receiveBufferSize = unsupported;
|
|
262
|
+
setReceiveBufferSize = unsupported;
|
|
263
|
+
sendBufferSize = unsupported;
|
|
264
|
+
setSendBufferSize = unsupported;
|
|
265
|
+
subscribe() {
|
|
266
|
+
return pollableCreate();
|
|
267
|
+
}
|
|
268
|
+
[symbolDispose]() { }
|
|
269
|
+
}
|
|
270
|
+
this.udp = {
|
|
271
|
+
IncomingDatagramStream,
|
|
272
|
+
OutgoingDatagramStream,
|
|
273
|
+
UdpSocket,
|
|
274
|
+
};
|
|
275
|
+
this.udpCreateSocket = {
|
|
276
|
+
createUdpSocket: (family) => new UdpSocket(family),
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
createClient(localAddress) {
|
|
280
|
+
const client = new InMemoryUdpClient((bytes, serverAddress) => {
|
|
281
|
+
const key = addressKey(serverAddress);
|
|
282
|
+
const queue = this.#datagrams.get(key);
|
|
283
|
+
const incoming = { data: new Uint8Array(bytes), remoteAddress: localAddress };
|
|
284
|
+
if (queue) {
|
|
285
|
+
queue.push(incoming);
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
this.#datagrams.set(key, [incoming]);
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
this.#clients.set(addressKey(localAddress), client);
|
|
292
|
+
return client;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * as cli from "./cli.js";
|
|
2
|
+
export * as clocks from "./clocks.js";
|
|
3
|
+
export * as filesystem from "./filesystem.js";
|
|
4
|
+
export * as http from "./http.js";
|
|
5
|
+
export * as io from "./io.js";
|
|
6
|
+
export * as random from "./random.js";
|
|
7
|
+
export * as sockets from "./sockets.js";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * as cli from "./cli.js";
|
|
2
|
+
export * as clocks from "./clocks.js";
|
|
3
|
+
export * as filesystem from "./filesystem.js";
|
|
4
|
+
export * as http from "./http.js";
|
|
5
|
+
export * as io from "./io.js";
|
|
6
|
+
export * as random from "./random.js";
|
|
7
|
+
export * as sockets from "./sockets.js";
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { error as ErrorNamespace, poll as PollNamespace, streams as StreamsNamespace } from "../../types/io.js";
|
|
2
|
+
declare const symbolDispose: symbol;
|
|
3
|
+
type IInputStream = StreamsNamespace.InputStream;
|
|
4
|
+
type IOutputStream = StreamsNamespace.OutputStream;
|
|
5
|
+
/**
|
|
6
|
+
* Handler interface for creating custom input streams
|
|
7
|
+
*/
|
|
8
|
+
export type InputStreamHandler = Partial<IInputStream> & Required<Pick<IInputStream, "blockingRead">> & {
|
|
9
|
+
drop?: () => void;
|
|
10
|
+
};
|
|
11
|
+
export interface PollableSource {
|
|
12
|
+
ready(): boolean;
|
|
13
|
+
wait(): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Handler interface for creating custom output streams
|
|
17
|
+
*/
|
|
18
|
+
export type OutputStreamHandler = Partial<IOutputStream> & Required<Pick<IOutputStream, "write">> & {
|
|
19
|
+
drop?: () => void;
|
|
20
|
+
};
|
|
21
|
+
export declare const ioErrorCreate: (message: string) => ErrorNamespace.Error;
|
|
22
|
+
declare class InputStream implements IInputStream {
|
|
23
|
+
#private;
|
|
24
|
+
[symbolDispose]: () => void;
|
|
25
|
+
id: number;
|
|
26
|
+
handler: InputStreamHandler;
|
|
27
|
+
static _create(handler: InputStreamHandler): InputStream;
|
|
28
|
+
read(len: bigint): Uint8Array<ArrayBufferLike>;
|
|
29
|
+
blockingRead(len: bigint): Uint8Array<ArrayBufferLike>;
|
|
30
|
+
skip(len: bigint): bigint;
|
|
31
|
+
blockingSkip(len: bigint): bigint;
|
|
32
|
+
subscribe(): PollNamespace.Pollable | Pollable;
|
|
33
|
+
}
|
|
34
|
+
export declare const inputStreamCreate: typeof InputStream._create;
|
|
35
|
+
declare class OutputStream implements IOutputStream {
|
|
36
|
+
#private;
|
|
37
|
+
[symbolDispose]: () => void;
|
|
38
|
+
id: number;
|
|
39
|
+
open: boolean;
|
|
40
|
+
handler: OutputStreamHandler;
|
|
41
|
+
static _create(handler: OutputStreamHandler): OutputStream;
|
|
42
|
+
checkWrite(): bigint;
|
|
43
|
+
write(buf: Uint8Array): void;
|
|
44
|
+
blockingWriteAndFlush(buf: Uint8Array): void;
|
|
45
|
+
flush(): void;
|
|
46
|
+
blockingFlush(): void;
|
|
47
|
+
writeZeroes(len: bigint): void;
|
|
48
|
+
blockingWriteZeroesAndFlush(len: bigint): void;
|
|
49
|
+
splice(src: InputStream, len: bigint): bigint;
|
|
50
|
+
blockingSplice(src: InputStream, len: bigint): bigint;
|
|
51
|
+
subscribe(): PollNamespace.Pollable | Pollable;
|
|
52
|
+
}
|
|
53
|
+
export declare const outputStreamCreate: typeof OutputStream._create;
|
|
54
|
+
export declare const error: typeof ErrorNamespace;
|
|
55
|
+
export declare const streams: typeof StreamsNamespace;
|
|
56
|
+
declare class Pollable implements PollNamespace.Pollable {
|
|
57
|
+
#private;
|
|
58
|
+
[symbolDispose]: () => void;
|
|
59
|
+
static _create(source?: Promise<void> | PollableSource): Pollable;
|
|
60
|
+
ready(): boolean;
|
|
61
|
+
block(): Promise<void>;
|
|
62
|
+
_onDispose(callback: () => void): void;
|
|
63
|
+
_invalidate(): void;
|
|
64
|
+
}
|
|
65
|
+
export declare const pollableCreate: typeof Pollable._create;
|
|
66
|
+
export declare const poll: typeof PollNamespace;
|
|
67
|
+
export {};
|