@swmansion/popcorn 0.3.2 → 0.4.0-next.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 +1 -1
- package/NOTICE +12 -0
- package/README.md +78 -2
- package/dist/beam.d.ts +10 -0
- package/dist/errors.d.ts +96 -39
- package/dist/etf.d.ts +38 -0
- package/dist/events.d.ts +82 -0
- package/dist/index.d.ts +7 -3
- package/dist/index.mjs +1287 -2
- package/dist/plugins/beam_tools/lib/popcorn/beam_tools/beam_patcher.ex +184 -0
- package/dist/plugins/beam_tools/lib/popcorn/beam_tools/cli.ex +74 -0
- package/dist/plugins/beam_tools/lib/popcorn/beam_tools/packager.ex +540 -0
- package/dist/plugins/beam_tools/mix.exs +16 -0
- package/dist/plugins/beam_tools/patches/kernel/prim_tty.erl +13 -0
- package/dist/plugins/beam_tools/patches/stdlib/beam_lib.erl +27 -0
- package/dist/plugins/esbuild.d.ts +10 -2
- package/dist/plugins/esbuild.mjs +39 -34
- package/dist/plugins/rollup.d.ts +10 -2
- package/dist/plugins/rollup.mjs +46 -25
- package/dist/plugins/shared.d.ts +54 -4
- package/dist/plugins/shared.mjs +207 -0
- package/dist/plugins/vite.d.ts +17 -2
- package/dist/plugins/vite.mjs +201 -75
- package/dist/popcorn.d.ts +237 -110
- package/dist/runtimes/core/beam.emu.mjs +141 -0
- package/dist/runtimes/core/beam.mjs +141 -0
- package/dist/runtimes/core/beam.wasm +0 -0
- package/dist/runtimes/core/manifest.json +1 -0
- package/dist/runtimes/crypto/beam.emu.mjs +520 -0
- package/dist/runtimes/crypto/beam.mjs +520 -0
- package/dist/runtimes/crypto/beam.wasm +0 -0
- package/dist/runtimes/crypto/manifest.json +1 -0
- package/dist/tar.d.ts +4 -0
- package/dist/types.d.ts +108 -63
- package/dist/utils.d.ts +7 -0
- package/dist/worker.d.ts +1 -0
- package/dist/worker.mjs +765 -0
- package/package.json +20 -28
- package/dist/AtomVM.mjs +0 -7992
- package/dist/AtomVM.wasm +0 -0
- package/dist/bridge.d.ts +0 -22
- package/dist/bridge.mjs +0 -66
- package/dist/errors.mjs +0 -55
- package/dist/iframe.d.ts +0 -1
- package/dist/iframe.mjs +0 -215
- package/dist/popcorn.mjs +0 -381
- package/dist/types.mjs +0 -25
package/dist/popcorn.d.ts
CHANGED
|
@@ -1,138 +1,265 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type
|
|
3
|
-
import type {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
1
|
+
import { type Result } from "./errors";
|
|
2
|
+
import { type PopcornEvent } from "./events";
|
|
3
|
+
import type { AnyValue, BeamBootOptions, OtpErrorPayload, Pid, TtySize } from "./types";
|
|
4
|
+
/** Output type for a terminal. */
|
|
5
|
+
type TtyOutput = "text" | "bytes";
|
|
6
|
+
type OutputChunk<Output extends TtyOutput> = Output extends "bytes" ? Uint8Array : string;
|
|
7
|
+
/** Browser VM configuration. */
|
|
8
|
+
export type PopcornOpts<Output extends TtyOutput = "text"> = {
|
|
9
|
+
beam?: Pick<BeamBootOptions, "emulatorArgs" | "extraArgs" | "env"> & {
|
|
10
|
+
/**
|
|
11
|
+
* Asset directory URL.
|
|
12
|
+
*
|
|
13
|
+
* Must end with `/`. Defaults to `otp/` next to the worker.
|
|
14
|
+
*/
|
|
15
|
+
otpAssetsRoot?: string;
|
|
16
|
+
};
|
|
17
|
+
tty?: {
|
|
18
|
+
/** Initial terminal size. Defaults to 80 columns and 24 rows. */
|
|
19
|
+
size?: TtySize;
|
|
20
|
+
/** Output callback format. Defaults to `text` with streamed UTF-8 decoding. Use `bytes` for raw chunks. */
|
|
21
|
+
output?: Output;
|
|
22
|
+
};
|
|
23
|
+
timeoutsMs?: {
|
|
24
|
+
/**
|
|
25
|
+
* Maximum wait for the VM bridge.
|
|
26
|
+
*
|
|
27
|
+
* Defaults to 10 000 ms.
|
|
28
|
+
*/
|
|
29
|
+
boot?: number;
|
|
30
|
+
/**
|
|
31
|
+
* Maximum wait for entrypoint startup after bridge readiness.
|
|
32
|
+
*
|
|
33
|
+
* Defaults to 60 000 ms.
|
|
34
|
+
*/
|
|
35
|
+
appStartup?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Maximum wait for a send resolving its process target.
|
|
38
|
+
*
|
|
39
|
+
* Defaults to 5 000 ms.
|
|
40
|
+
*/
|
|
41
|
+
send?: number;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Receives stdout.
|
|
45
|
+
*
|
|
46
|
+
* Defaults to `console.log`.
|
|
47
|
+
* When `tty.output` is "bytes", we pass an `ArrayBuffer` as an argument and `string` otherwise
|
|
48
|
+
*/
|
|
49
|
+
onStdout?: (chunk: OutputChunk<Output>) => void;
|
|
50
|
+
/**
|
|
51
|
+
* Receives stderr.
|
|
52
|
+
*
|
|
53
|
+
* Defaults to `console.error`.
|
|
54
|
+
* When `tty.output` is "bytes", we pass an `ArrayBuffer` as an argument and `string` otherwise
|
|
55
|
+
*/
|
|
56
|
+
onStderr?: (chunk: OutputChunk<Output>) => void;
|
|
57
|
+
/**
|
|
58
|
+
* Receives VM errors and exits before shutdown.
|
|
59
|
+
*
|
|
60
|
+
* Defaults to console output.
|
|
61
|
+
*/
|
|
62
|
+
onError?: (event: OtpErrorPayload) => void;
|
|
63
|
+
/**
|
|
64
|
+
* Module worker URL.
|
|
65
|
+
*
|
|
66
|
+
* Defaults to the worker included with the package.
|
|
67
|
+
*/
|
|
68
|
+
workerUrl?: string | URL;
|
|
24
69
|
};
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
70
|
+
type VmExitReason = {
|
|
71
|
+
reason: "deinit";
|
|
72
|
+
} | {
|
|
73
|
+
reason: "abort";
|
|
74
|
+
data: string;
|
|
75
|
+
} | {
|
|
76
|
+
reason: "error";
|
|
77
|
+
data: string;
|
|
78
|
+
} | {
|
|
79
|
+
reason: "exit";
|
|
80
|
+
data: number;
|
|
29
81
|
};
|
|
30
|
-
|
|
31
|
-
export type CallOptions = {
|
|
32
|
-
/** Registered Elixir process name. */
|
|
33
|
-
process?: string;
|
|
34
|
-
/** Timeout (in milliseconds) for the call */
|
|
82
|
+
type CallOpts = {
|
|
35
83
|
timeoutMs?: number;
|
|
84
|
+
proxy?: string;
|
|
36
85
|
};
|
|
37
|
-
type
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
86
|
+
export type GenServer = {
|
|
87
|
+
/**
|
|
88
|
+
* Calls a GenServer by registered name or {@link Pid} and waits for its reply.
|
|
89
|
+
*
|
|
90
|
+
* Requires a running `Popcorn.Proxy`, registered as `popcorn_proxy` by default.
|
|
91
|
+
*
|
|
92
|
+
* @param opts - `timeoutMs` defaults to 5 000 ms. `proxy` allows to select another registered proxy.
|
|
93
|
+
* @returns A {@link Result} with the reply or a bridge, VM, timeout, or GenServer error.
|
|
94
|
+
*
|
|
95
|
+
* GenServer failures use `genserver:noproc`, `genserver:exit`, or `genserver:unserializable`.
|
|
96
|
+
* A call timeout does not cancel server work.
|
|
97
|
+
*/
|
|
98
|
+
call(target: string | Pid, request?: AnyValue, opts?: CallOpts): Promise<Result<AnyValue>>;
|
|
99
|
+
/**
|
|
100
|
+
* Sends a cast through the proxy.
|
|
101
|
+
*
|
|
102
|
+
* Success confirms delivery to the proxy
|
|
103
|
+
* @see {@link call}
|
|
104
|
+
* @param opts - `proxy` allows to select another registered proxy.
|
|
105
|
+
*/
|
|
106
|
+
cast(target: string | Pid, request?: AnyValue, opts?: {
|
|
107
|
+
proxy?: string;
|
|
108
|
+
}): Promise<Result<null>>;
|
|
49
109
|
};
|
|
50
|
-
type LogType = "stdout" | "stderr";
|
|
51
|
-
type LogListener = (message: string) => void;
|
|
52
|
-
type MessageHandler = (eventName: string, payload: AnySerializable) => void;
|
|
53
110
|
/**
|
|
54
|
-
*
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
private
|
|
60
|
-
private bridgeConfig;
|
|
61
|
-
private debug;
|
|
62
|
-
private bundleURLs;
|
|
111
|
+
* A BEAM VM in a browser worker.
|
|
112
|
+
*
|
|
113
|
+
* Use {@link Popcorn.init} to create and start an instance.
|
|
114
|
+
**/
|
|
115
|
+
export declare class Popcorn<Output extends TtyOutput = "text"> {
|
|
116
|
+
private vmWorker;
|
|
63
117
|
private state;
|
|
64
|
-
private
|
|
65
|
-
private
|
|
66
|
-
private
|
|
67
|
-
private
|
|
68
|
-
private
|
|
69
|
-
private
|
|
70
|
-
private
|
|
71
|
-
private
|
|
72
|
-
private
|
|
118
|
+
private readonly opts;
|
|
119
|
+
private readonly ttySize;
|
|
120
|
+
private output;
|
|
121
|
+
private requestSeq;
|
|
122
|
+
private settleBoot;
|
|
123
|
+
private readonly eventHandlers;
|
|
124
|
+
private readonly pendingSends;
|
|
125
|
+
private readonly pendingCalls;
|
|
126
|
+
private callSeq;
|
|
127
|
+
private readonly trackedValues;
|
|
128
|
+
private trackedKeySeq;
|
|
129
|
+
private io;
|
|
130
|
+
private vmReady;
|
|
131
|
+
readonly genserver: GenServer;
|
|
132
|
+
private readonly TrackedValue;
|
|
133
|
+
private Pid;
|
|
134
|
+
private readonly onWorkerMessage;
|
|
73
135
|
/**
|
|
74
|
-
* Creates
|
|
75
|
-
* Returns after the Elixir app calls `Popcorn.Wasm.ready/0,1`.
|
|
136
|
+
* Creates the worker.
|
|
76
137
|
*
|
|
77
|
-
* @
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
*
|
|
83
|
-
*
|
|
138
|
+
* Call {@link boot} to start the VM.
|
|
139
|
+
**/
|
|
140
|
+
constructor(opts: PopcornOpts<Output>);
|
|
141
|
+
private spawnWorker;
|
|
142
|
+
/**
|
|
143
|
+
* Creates an instance and waits for {@link boot}.
|
|
144
|
+
*
|
|
145
|
+
* For startup messages, use the constructor and register {@link onEvent} before boot.
|
|
146
|
+
*
|
|
147
|
+
* @returns Ok tuple or `runtime:eval-unavailable` if the page blocks JavaScript evaluation.
|
|
84
148
|
*/
|
|
85
|
-
static init(
|
|
86
|
-
private mount;
|
|
149
|
+
static init<Output extends TtyOutput = "text">(opts: PopcornOpts<Output>): Promise<Result<Popcorn<Output>>>;
|
|
87
150
|
/**
|
|
88
|
-
*
|
|
151
|
+
* Starts the VM and waits for its bridge and entrypoint application.
|
|
89
152
|
*
|
|
90
|
-
*
|
|
153
|
+
* Without an entrypoint, waits only for the bridge.
|
|
91
154
|
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
155
|
+
* After shutdown, starts a fresh VM with the original options.
|
|
156
|
+
*
|
|
157
|
+
* @returns Ok tuple with `this` if boot completes or error tuple.
|
|
94
158
|
*
|
|
95
159
|
* @example
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
* );
|
|
100
|
-
*
|
|
101
|
-
*
|
|
160
|
+
* ```ts
|
|
161
|
+
* const popcorn = new Popcorn({});
|
|
162
|
+
* popcorn.onEvent((message) => console.log(message));
|
|
163
|
+
* const result = await popcorn.boot();
|
|
164
|
+
* if (!result.ok) throw result.error;
|
|
165
|
+
* ```
|
|
102
166
|
*/
|
|
103
|
-
|
|
167
|
+
boot(): Promise<Result<Popcorn<Output>>>;
|
|
104
168
|
/**
|
|
105
|
-
*
|
|
169
|
+
* Queues terminal input.
|
|
170
|
+
*
|
|
171
|
+
* Encodes strings as UTF-8 and copies byte arrays. Does not append a newline.
|
|
106
172
|
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
173
|
+
* Returns `stdio:overflow` if the chunk exceeds the remaining 64 KiB queue capacity.
|
|
174
|
+
* An overflow leaves the queue unchanged.
|
|
109
175
|
*/
|
|
110
|
-
|
|
176
|
+
writeStdin(chunk: string | Uint8Array): Result<null>;
|
|
111
177
|
/**
|
|
112
|
-
*
|
|
178
|
+
* Sends new terminal dimensions to a booted VM.
|
|
179
|
+
*
|
|
180
|
+
* Each dimension must be between 1 and 65,535.
|
|
113
181
|
*/
|
|
114
|
-
|
|
115
|
-
private teardownBridge;
|
|
182
|
+
resizeTty(columns: number, rows: number): Result<null>;
|
|
116
183
|
/**
|
|
117
|
-
*
|
|
184
|
+
* Sends a payload to a registered process name or a {@link Pid} from this VM boot.
|
|
185
|
+
*
|
|
186
|
+
* The process receives `{wasm, Payload}`.
|
|
187
|
+
* A send timeout does not cancel delivery.
|
|
188
|
+
* Uses the value conversions in {@link AnyValue}. An omitted, `null`, or `undefined` payload becomes an empty map.
|
|
189
|
+
*
|
|
190
|
+
* @returns Ok tuple or `bridge:not-started` before boot and `vm:exited` after shutdown.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* Send an Erlang `{ok, <<"value">>}` tuple to a registered `receiver` process.
|
|
194
|
+
*
|
|
195
|
+
* ```ts
|
|
196
|
+
* const result = await popcorn.send("receiver", tuple(atom("ok"), "value"));
|
|
197
|
+
* if (!result.ok) throw result.error;
|
|
198
|
+
* ```
|
|
199
|
+
*
|
|
200
|
+
* @see {@link AnyValue}
|
|
201
|
+
* @see {@link atom}
|
|
202
|
+
* @see {@link tuple}
|
|
118
203
|
*/
|
|
119
|
-
|
|
204
|
+
send(rawTarget: string | Pid, payload?: AnyValue): Promise<Result<null>>;
|
|
205
|
+
private sendBridge;
|
|
120
206
|
/**
|
|
121
|
-
*
|
|
207
|
+
* Registers a handler for BEAM message payloads.
|
|
208
|
+
*
|
|
209
|
+
* Messages with no handlers are lost. Startup messages can arrive before {@link boot} resolves.
|
|
210
|
+
* VM errors and terminal output use the callbacks in {@link PopcornOpts}.
|
|
211
|
+
*
|
|
212
|
+
* @returns a function that removes the handler.
|
|
122
213
|
*/
|
|
123
|
-
|
|
124
|
-
private notifyLogListeners;
|
|
214
|
+
onEvent(handler: (event: PopcornEvent) => void): () => void;
|
|
125
215
|
/**
|
|
126
|
-
*
|
|
216
|
+
* Stops the worker and completes pending sends and calls with `vm:exited`.
|
|
217
|
+
*
|
|
218
|
+
* Releases tracked values and runs their cleanup callbacks.
|
|
219
|
+
* Keeps event handlers for the next boot. Repeated calls have no effect.
|
|
127
220
|
*/
|
|
128
|
-
|
|
129
|
-
private
|
|
130
|
-
private
|
|
131
|
-
private
|
|
132
|
-
private
|
|
133
|
-
private
|
|
134
|
-
private
|
|
135
|
-
|
|
136
|
-
private
|
|
137
|
-
private
|
|
221
|
+
deinit(reason?: VmExitReason): void;
|
|
222
|
+
private clearTrackedValues;
|
|
223
|
+
private emit;
|
|
224
|
+
private completeCall;
|
|
225
|
+
private parseCallReply;
|
|
226
|
+
private call;
|
|
227
|
+
private callBridge;
|
|
228
|
+
private cast;
|
|
229
|
+
private castBridge;
|
|
230
|
+
private nextCallId;
|
|
231
|
+
private runJs;
|
|
232
|
+
private asRef;
|
|
233
|
+
private sendRunJsReply;
|
|
234
|
+
private jsWithCurrentEnv;
|
|
235
|
+
private reviveHandles;
|
|
236
|
+
/** Maps pids and `TrackedValue`s during encoding, collecting handles into
|
|
237
|
+
* `tracked` for the caller to register once encoding succeeds. */
|
|
238
|
+
private handleMapper;
|
|
239
|
+
private deleteTrackedValue;
|
|
240
|
+
private completeSend;
|
|
241
|
+
private nextRequestId;
|
|
242
|
+
private handleStdout;
|
|
243
|
+
private handleStderr;
|
|
244
|
+
private handleOtpError;
|
|
138
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* Thread counts for {@link schedulers}.
|
|
248
|
+
*
|
|
249
|
+
* Each count must be positive.
|
|
250
|
+
*/
|
|
251
|
+
export type SchedulerOptions = {
|
|
252
|
+
/** Regular schedulers. */
|
|
253
|
+
base: number;
|
|
254
|
+
/** Dirty CPU schedulers. */
|
|
255
|
+
dirtyCpu: number;
|
|
256
|
+
/** Dirty I/O schedulers. */
|
|
257
|
+
dirtyIo: number;
|
|
258
|
+
};
|
|
259
|
+
/**
|
|
260
|
+
* Builds `beam.emulatorArgs` for scheduler counts.
|
|
261
|
+
*
|
|
262
|
+
* Defaults to one scheduler of each type.
|
|
263
|
+
*/
|
|
264
|
+
export declare function schedulers(opts: SchedulerOptions): string[];
|
|
265
|
+
export {};
|