@bytecodealliance/preview2-shim 0.18.1 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/dist/browser/cli.d.ts +16 -0
  2. package/dist/browser/cli.js +109 -0
  3. package/dist/browser/clocks.d.ts +3 -0
  4. package/dist/browser/clocks.js +36 -0
  5. package/dist/browser/config.d.ts +2 -0
  6. package/{lib → dist}/browser/config.js +2 -4
  7. package/dist/browser/environment.d.ts +5 -0
  8. package/dist/browser/environment.js +24 -0
  9. package/dist/browser/filesystem.d.ts +132 -0
  10. package/dist/browser/filesystem.js +464 -0
  11. package/dist/browser/http.d.ts +4 -0
  12. package/dist/browser/http.js +643 -0
  13. package/dist/browser/index.d.ts +7 -0
  14. package/dist/browser/index.js +7 -0
  15. package/dist/browser/io.d.ts +58 -0
  16. package/dist/browser/io.js +205 -0
  17. package/dist/browser/random.d.ts +4 -0
  18. package/dist/browser/random.js +49 -0
  19. package/dist/browser/sockets.d.ts +8 -0
  20. package/dist/browser/sockets.js +66 -0
  21. package/dist/common/instantiation.d.ts +97 -0
  22. package/dist/common/instantiation.js +227 -0
  23. package/dist/io/calls.d.ts +91 -0
  24. package/{lib → dist}/io/calls.js +4 -19
  25. package/dist/io/worker-http.d.ts +17 -0
  26. package/dist/io/worker-http.js +192 -0
  27. package/dist/io/worker-io.d.ts +84 -0
  28. package/dist/io/worker-io.js +375 -0
  29. package/dist/io/worker-socket-tcp.d.ts +34 -0
  30. package/dist/io/worker-socket-tcp.js +251 -0
  31. package/dist/io/worker-socket-udp.d.ts +54 -0
  32. package/dist/io/worker-socket-udp.js +492 -0
  33. package/dist/io/worker-sockets.d.ts +32 -0
  34. package/dist/io/worker-sockets.js +265 -0
  35. package/dist/io/worker-thread.d.ts +73 -0
  36. package/dist/io/worker-thread.js +791 -0
  37. package/dist/nodejs/cli.d.ts +30 -0
  38. package/dist/nodejs/cli.js +86 -0
  39. package/dist/nodejs/clocks.d.ts +3 -0
  40. package/dist/nodejs/clocks.js +61 -0
  41. package/dist/nodejs/filesystem.d.ts +113 -0
  42. package/dist/nodejs/filesystem.js +758 -0
  43. package/dist/nodejs/http.d.ts +82 -0
  44. package/dist/nodejs/http.js +674 -0
  45. package/dist/nodejs/index.d.ts +7 -0
  46. package/dist/nodejs/index.js +7 -0
  47. package/dist/nodejs/io.d.ts +1 -0
  48. package/dist/nodejs/io.js +1 -0
  49. package/dist/nodejs/random.d.ts +4 -0
  50. package/dist/nodejs/random.js +42 -0
  51. package/dist/nodejs/sockets.d.ts +21 -0
  52. package/dist/nodejs/sockets.js +482 -0
  53. package/dist/synckit/index.d.ts +2 -0
  54. package/dist/synckit/index.js +117 -0
  55. package/package.json +26 -13
  56. package/types/instantiation.d.ts +7 -7
  57. package/lib/browser/cli.js +0 -135
  58. package/lib/browser/clocks.js +0 -39
  59. package/lib/browser/environment.js +0 -29
  60. package/lib/browser/filesystem.js +0 -503
  61. package/lib/browser/http.js +0 -707
  62. package/lib/browser/index.js +0 -9
  63. package/lib/browser/io.js +0 -262
  64. package/lib/browser/random.js +0 -56
  65. package/lib/browser/sockets.js +0 -88
  66. package/lib/common/instantiation.js +0 -253
  67. package/lib/io/worker-http.js +0 -206
  68. package/lib/io/worker-io.js +0 -468
  69. package/lib/io/worker-socket-tcp.js +0 -331
  70. package/lib/io/worker-socket-udp.js +0 -587
  71. package/lib/io/worker-sockets.js +0 -364
  72. package/lib/io/worker-thread.js +0 -1051
  73. package/lib/nodejs/cli.js +0 -109
  74. package/lib/nodejs/clocks.js +0 -67
  75. package/lib/nodejs/filesystem.js +0 -829
  76. package/lib/nodejs/http.js +0 -764
  77. package/lib/nodejs/index.js +0 -9
  78. package/lib/nodejs/io.js +0 -1
  79. package/lib/nodejs/random.js +0 -49
  80. package/lib/nodejs/sockets.js +0 -565
  81. package/lib/synckit/index.js +0 -127
@@ -0,0 +1,58 @@
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
+ /**
12
+ * Handler interface for creating custom output streams
13
+ */
14
+ export type OutputStreamHandler = Partial<IOutputStream> & Required<Pick<IOutputStream, "write">> & {
15
+ drop?: () => void;
16
+ };
17
+ declare class InputStream implements IInputStream {
18
+ [symbolDispose]: () => void;
19
+ id: number;
20
+ handler: InputStreamHandler;
21
+ static _create(handler: InputStreamHandler): InputStream;
22
+ read(len: bigint): Uint8Array<ArrayBufferLike>;
23
+ blockingRead(len: bigint): Uint8Array<ArrayBufferLike>;
24
+ skip(len: bigint): bigint;
25
+ blockingSkip(len: bigint): bigint;
26
+ subscribe(): PollNamespace.Pollable | Pollable;
27
+ }
28
+ export declare const inputStreamCreate: typeof InputStream._create;
29
+ declare class OutputStream implements IOutputStream {
30
+ [symbolDispose]: () => void;
31
+ id: number;
32
+ open: boolean;
33
+ handler: OutputStreamHandler;
34
+ static _create(handler: OutputStreamHandler): OutputStream;
35
+ checkWrite(): bigint;
36
+ write(buf: Uint8Array): void;
37
+ blockingWriteAndFlush(buf: Uint8Array): void;
38
+ flush(): void;
39
+ blockingFlush(): void;
40
+ writeZeroes(len: bigint): void;
41
+ blockingWriteZeroesAndFlush(len: bigint): void;
42
+ splice(src: InputStream, len: bigint): bigint;
43
+ blockingSplice(_src: InputStream, _len: bigint): bigint;
44
+ subscribe(): PollNamespace.Pollable | Pollable;
45
+ }
46
+ export declare const outputStreamCreate: typeof OutputStream._create;
47
+ export declare const error: typeof ErrorNamespace;
48
+ export declare const streams: typeof StreamsNamespace;
49
+ declare class Pollable implements PollNamespace.Pollable {
50
+ #private;
51
+ [symbolDispose]: () => void;
52
+ static _create(promise?: Promise<void>): Pollable;
53
+ ready(): boolean;
54
+ block(): Promise<void>;
55
+ }
56
+ export declare const pollableCreate: typeof Pollable._create;
57
+ export declare const poll: typeof PollNamespace;
58
+ export {};
@@ -0,0 +1,205 @@
1
+ let id = 0;
2
+ const symbolDispose = Symbol.dispose || Symbol.for("dispose");
3
+ class IoError extends Error {
4
+ toDebugString() {
5
+ return this.message;
6
+ }
7
+ }
8
+ class InputStream {
9
+ id;
10
+ handler;
11
+ static _create(handler) {
12
+ const stream = new InputStream();
13
+ if (!handler) {
14
+ console.trace("no handler");
15
+ }
16
+ stream.id = ++id;
17
+ stream.handler = handler;
18
+ return stream;
19
+ }
20
+ read(len) {
21
+ if (this.handler.read) {
22
+ return this.handler.read(len);
23
+ }
24
+ return this.handler.blockingRead.call(this, len);
25
+ }
26
+ blockingRead(len) {
27
+ return this.handler.blockingRead.call(this, len);
28
+ }
29
+ skip(len) {
30
+ if (this.handler.skip) {
31
+ return this.handler.skip.call(this, len);
32
+ }
33
+ if (this.handler.read) {
34
+ const bytes = this.handler.read.call(this, len);
35
+ return BigInt(bytes.byteLength);
36
+ }
37
+ return this.blockingSkip.call(this, len);
38
+ }
39
+ blockingSkip(len) {
40
+ if (this.handler.blockingSkip) {
41
+ return this.handler.blockingSkip.call(this, len);
42
+ }
43
+ const bytes = this.handler.blockingRead.call(this, len);
44
+ return BigInt(bytes.byteLength);
45
+ }
46
+ subscribe() {
47
+ if (this.handler.subscribe) {
48
+ return this.handler.subscribe();
49
+ }
50
+ return new Pollable();
51
+ }
52
+ [symbolDispose]() {
53
+ if (this.handler.drop) {
54
+ this.handler.drop.call(this);
55
+ }
56
+ }
57
+ }
58
+ export const inputStreamCreate = InputStream._create;
59
+ // @ts-expect-error - Deleting static method
60
+ delete InputStream._create;
61
+ class OutputStream {
62
+ id;
63
+ open;
64
+ handler;
65
+ static _create(handler) {
66
+ const stream = new OutputStream();
67
+ if (!handler) {
68
+ console.trace("no handler");
69
+ }
70
+ stream.id = ++id;
71
+ stream.open = true;
72
+ stream.handler = handler;
73
+ return stream;
74
+ }
75
+ checkWrite() {
76
+ if (!this.open) {
77
+ return 0n;
78
+ }
79
+ if (this.handler.checkWrite) {
80
+ return this.handler.checkWrite.call(this);
81
+ }
82
+ return 1000000n;
83
+ }
84
+ write(buf) {
85
+ this.handler.write.call(this, buf);
86
+ }
87
+ blockingWriteAndFlush(buf) {
88
+ if (this.handler.blockingWriteAndFlush) {
89
+ return this.handler.blockingWriteAndFlush.call(this, buf);
90
+ }
91
+ this.handler.write.call(this, buf);
92
+ }
93
+ flush() {
94
+ if (this.handler.flush) {
95
+ this.handler.flush.call(this);
96
+ }
97
+ }
98
+ blockingFlush() {
99
+ this.open = true;
100
+ if (this.handler.blockingFlush) {
101
+ this.handler.blockingFlush.call(this);
102
+ }
103
+ }
104
+ writeZeroes(len) {
105
+ this.write.call(this, new Uint8Array(Number(len)));
106
+ }
107
+ blockingWriteZeroesAndFlush(len) {
108
+ this.blockingWriteAndFlush.call(this, new Uint8Array(Number(len)));
109
+ }
110
+ splice(src, len) {
111
+ const spliceLen = Math.min(Number(len), Number(this.checkWrite.call(this)));
112
+ const bytes = src.read(BigInt(spliceLen));
113
+ this.write.call(this, bytes);
114
+ return BigInt(bytes.byteLength);
115
+ }
116
+ blockingSplice(_src, _len) {
117
+ console.log(`[streams] Blocking splice ${this.id}`);
118
+ return 0n;
119
+ }
120
+ subscribe() {
121
+ if (this.handler.subscribe) {
122
+ return this.handler.subscribe();
123
+ }
124
+ return new Pollable();
125
+ }
126
+ [symbolDispose]() { }
127
+ }
128
+ export const outputStreamCreate = OutputStream._create;
129
+ // @ts-expect-error - Deleting static method
130
+ delete OutputStream._create;
131
+ export const error = {
132
+ Error: IoError,
133
+ };
134
+ export const streams = { InputStream, OutputStream };
135
+ class Pollable {
136
+ #ready = false;
137
+ #promise = null;
138
+ static _create(promise) {
139
+ const pollable = new Pollable();
140
+ if (!promise) {
141
+ pollable.#ready = true;
142
+ }
143
+ else {
144
+ pollable.#promise = promise.then(() => {
145
+ pollable.#ready = true;
146
+ }, () => {
147
+ pollable.#ready = true;
148
+ });
149
+ }
150
+ return pollable;
151
+ }
152
+ ready() {
153
+ return this.#ready;
154
+ }
155
+ block() {
156
+ if (this.#ready) {
157
+ return Promise.resolve();
158
+ }
159
+ return this.#promise || Promise.resolve();
160
+ }
161
+ [symbolDispose]() {
162
+ this.#promise = null;
163
+ }
164
+ }
165
+ export const pollableCreate = Pollable._create;
166
+ // @ts-expect-error - Deleting static method
167
+ delete Pollable._create;
168
+ function pollList(list) {
169
+ if (list.length === 0) {
170
+ throw new Error("poll list must not be empty");
171
+ }
172
+ if (list.length > 0xffffffff) {
173
+ throw new Error("poll list length exceeds u32 index range");
174
+ }
175
+ const ready = [];
176
+ for (let i = 0; i < list.length; i++) {
177
+ if (list[i].ready()) {
178
+ ready.push(i);
179
+ }
180
+ }
181
+ if (ready.length > 0) {
182
+ return new Uint32Array(ready);
183
+ }
184
+ // None ready synchronously. Wait for the first to resolve via Promise.race,
185
+ // then sweep for any others that became ready concurrently.
186
+ return Promise.race(list.map((p, i) => p.block().then(() => {
187
+ const result = [i];
188
+ for (let j = 0; j < list.length; j++) {
189
+ if (j !== i && list[j].ready()) {
190
+ result.push(j);
191
+ }
192
+ }
193
+ return new Uint32Array(result);
194
+ })));
195
+ }
196
+ function pollOne(poll) {
197
+ return poll.block();
198
+ }
199
+ export const poll = {
200
+ Pollable,
201
+ pollList,
202
+ pollOne,
203
+ // @ts-expect-error Not matching signature from WIT
204
+ poll: pollList,
205
+ };
@@ -0,0 +1,4 @@
1
+ import type { insecure as InsecureNamespace, insecureSeed as InsecureSeedNamespace, random as RandomNamespace } from "../../types/random.js";
2
+ export declare const insecure: typeof InsecureNamespace;
3
+ export declare const insecureSeed: typeof InsecureSeedNamespace;
4
+ export declare const random: typeof RandomNamespace;
@@ -0,0 +1,49 @@
1
+ const MAX_BYTES = 65536;
2
+ let insecureRandomValue1, insecureRandomValue2;
3
+ export const insecure = {
4
+ getInsecureRandomBytes(len) {
5
+ return random.getRandomBytes(len);
6
+ },
7
+ getInsecureRandomU64() {
8
+ return random.getRandomU64();
9
+ },
10
+ };
11
+ let insecureSeedValue1, insecureSeedValue2;
12
+ export const insecureSeed = {
13
+ insecureSeed() {
14
+ if (insecureSeedValue1 === undefined || insecureSeedValue2 === undefined) {
15
+ insecureSeedValue1 = random.getRandomU64();
16
+ insecureSeedValue2 = random.getRandomU64();
17
+ }
18
+ return [insecureSeedValue1, insecureSeedValue2];
19
+ },
20
+ };
21
+ export const random = {
22
+ getRandomBytes(len) {
23
+ const bytes = new Uint8Array(Number(len));
24
+ if (len > MAX_BYTES) {
25
+ // this is the max bytes crypto.getRandomValues
26
+ // can do at once see https://developer.mozilla.org/en-US/docs/Web/API/window.crypto.getRandomValues
27
+ for (var generated = 0; generated < len; generated += MAX_BYTES) {
28
+ // buffer.slice automatically checks if the end is past the end of
29
+ // the buffer so we don't have to here
30
+ crypto.getRandomValues(bytes.subarray(generated, generated + MAX_BYTES));
31
+ }
32
+ }
33
+ else {
34
+ crypto.getRandomValues(bytes);
35
+ }
36
+ return bytes;
37
+ },
38
+ getRandomU64() {
39
+ return crypto.getRandomValues(new BigUint64Array(1))[0];
40
+ },
41
+ // @ts-expect-error Not defined in WIT
42
+ insecureRandom() {
43
+ if (insecureRandomValue1 === undefined || insecureRandomValue2 === undefined) {
44
+ insecureRandomValue1 = random.getRandomU64();
45
+ insecureRandomValue2 = random.getRandomU64();
46
+ }
47
+ return [insecureRandomValue1, insecureRandomValue2];
48
+ },
49
+ };
@@ -0,0 +1,8 @@
1
+ import type { instanceNetwork as InstanceNetworkNamespace, ipNameLookup as IpNameLookupNamespace, network as NetworkNamespace, tcpCreateSocket as TcpCreateSocketNamespace, tcp as TcpNamespace, udpCreateSocket as UdpCreateSocketNamespace, udp as UdpNamespace } from "../../types/sockets.js";
2
+ export declare const instanceNetwork: typeof InstanceNetworkNamespace;
3
+ export declare const ipNameLookup: typeof IpNameLookupNamespace;
4
+ export declare const network: typeof NetworkNamespace;
5
+ export declare const tcpCreateSocket: typeof TcpCreateSocketNamespace;
6
+ export declare const tcp: typeof TcpNamespace;
7
+ export declare const udpCreateSocket: typeof UdpCreateSocketNamespace;
8
+ export declare const udp: typeof UdpNamespace;
@@ -0,0 +1,66 @@
1
+ export const instanceNetwork = {
2
+ instanceNetwork() {
3
+ console.log(`[sockets] instance network`);
4
+ },
5
+ };
6
+ export const ipNameLookup = {
7
+ dropResolveAddressStream() { },
8
+ subscribe() { },
9
+ resolveAddresses() { },
10
+ resolveNextAddress() { },
11
+ nonBlocking() { },
12
+ setNonBlocking() { },
13
+ };
14
+ export const network = {
15
+ dropNetwork() { },
16
+ };
17
+ export const tcpCreateSocket = {
18
+ createTcpSocket() { },
19
+ };
20
+ export const tcp = {
21
+ subscribe() { },
22
+ dropTcpSocket() { },
23
+ bind() { },
24
+ connect() { },
25
+ listen() { },
26
+ accept() { },
27
+ localAddress() { },
28
+ remoteAddress() { },
29
+ addressFamily() { },
30
+ setListenBacklogSize() { },
31
+ keepAlive() { },
32
+ setKeepAlive() { },
33
+ noDelay() { },
34
+ setNoDelay() { },
35
+ unicastHopLimit() { },
36
+ setUnicastHopLimit() { },
37
+ receiveBufferSize() { },
38
+ setReceiveBufferSize() { },
39
+ sendBufferSize() { },
40
+ setSendBufferSize() { },
41
+ nonBlocking() { },
42
+ setNonBlocking() { },
43
+ shutdown() { },
44
+ };
45
+ export const udpCreateSocket = {
46
+ createUdpSocket() { },
47
+ };
48
+ export const udp = {
49
+ subscribe() { },
50
+ dropUdpSocket() { },
51
+ bind() { },
52
+ connect() { },
53
+ receive() { },
54
+ send() { },
55
+ localAddress() { },
56
+ remoteAddress() { },
57
+ addressFamily() { },
58
+ unicastHopLimit() { },
59
+ setUnicastHopLimit() { },
60
+ receiveBufferSize() { },
61
+ setReceiveBufferSize() { },
62
+ sendBufferSize() { },
63
+ setSendBufferSize() { },
64
+ nonBlocking() { },
65
+ setNonBlocking() { },
66
+ };
@@ -0,0 +1,97 @@
1
+ import type { WASIShimConfig, GetImportObjectArgs, WASIImportObject } from "../../types/instantiation.js";
2
+ /**
3
+ * (EXPERIMENTAL) A class that holds WASI shims and can be used to configure
4
+ * an instantiation of a WebAssembly component transpiled with jco
5
+ * (i.e. via `jco transpile`).
6
+ *
7
+ * Normally, transpiled components contain mapping for WASI interfaces
8
+ * and/or imports that import the relevant packages (ex. `@bytecodealliance/preview2-shim/clocks`)
9
+ * from the right sources.
10
+ *
11
+ * This function makes use of the `WASIShim` object to provide an object that can be easily
12
+ * fed to the `instantiate` function produced by a transpiled component:
13
+ *
14
+ * ```js
15
+ * import { WASIShim } from "@bytecodealliance/preview2-shim/instantiation"
16
+ * // ...
17
+ * import { instantiate } from "path/to/transpiled/component.js"
18
+ * // ...
19
+ * const component = await instantiate(null, new WASIShim().getImportObject())
20
+ * ```
21
+ *
22
+ * You can also replace imports that you'd like to override with custom implementations,
23
+ * by using the `WASIShim` object directly:
24
+ *
25
+ * ```js
26
+ * import { random } from "@bytecodealliance/preview2-shim"
27
+ * import { WASIShim } from "@bytecodealliance/preview2-shim/instantiation"
28
+ * // ...
29
+ * import { instantiate } from "path/to/transpiled/component.js"
30
+ * // ...
31
+ * const customWASIShim = new WASIShim({
32
+ * random: {
33
+ * // For these two interfaces we re-use the default provided shim
34
+ * random: random.random,
35
+ * insecure-seed: random.insecureSeed,
36
+ * // For insecure, we can supply our own custom implementation
37
+ * insecure: {
38
+ * ...
39
+ * }
40
+ * }
41
+ * });
42
+ *
43
+ * const component = await instantiate(null, customWASIShim.getImportObject())
44
+ * ```
45
+ *
46
+ * For sandboxing, you can configure preopens, environment variables, and other
47
+ * capabilities via the `sandbox` option:
48
+ *
49
+ * ```js
50
+ * import { WASIShim } from "@bytecodealliance/preview2-shim/instantiation"
51
+ *
52
+ * // Fully sandboxed - no filesystem, network, or env access
53
+ * const sandboxedShim = new WASIShim({
54
+ * sandbox: {
55
+ * preopens: {}, // No filesystem access
56
+ * env: {}, // No environment variables
57
+ * args: ['program'], // Custom arguments
58
+ * enableNetwork: false, // Disable network (default: true for backward compat)
59
+ * }
60
+ * });
61
+ *
62
+ * // Limited filesystem access
63
+ * const limitedShim = new WASIShim({
64
+ * sandbox: {
65
+ * preopens: {
66
+ * '/data': '/tmp/guest-data', // Guest sees /data, maps to /tmp/guest-data
67
+ * '/config': '/etc/app' // Guest sees /config, maps to /etc/app
68
+ * }
69
+ * }
70
+ * });
71
+ * ```
72
+ *
73
+ * Note that this object is similar but not identical to the Node `WASI` object --
74
+ * it is solely concerned with shimming of preview2 when dealing with a WebAssembly
75
+ * component transpiled by Jco. While this object *does* work with Node (and the browser)
76
+ * semantics are not the same as Node's `WASI` object.
77
+ *
78
+ * @class WASIShim
79
+ */
80
+ export declare class WASIShim {
81
+ #private;
82
+ /**
83
+ * Create a new WASIShim instance.
84
+ *
85
+ * @param config - Configuration options
86
+ */
87
+ constructor(config?: WASIShimConfig);
88
+ /**
89
+ * Generate an import object for the shim that can be used with
90
+ * functions like `instantiate` that are exposed from a transpiled
91
+ * WebAssembly component.
92
+ *
93
+ * @param opts - options for import object generation
94
+ * @returns WASIImportObject
95
+ */
96
+ getImportObject(opts?: GetImportObjectArgs): WASIImportObject;
97
+ }