@remix_labs/machine-starter 1.1460.0-dev → 1.1466.0-dev
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/index.js +94 -32
- package/package.json +2 -2
- package/start.js +2 -1
package/index.js
CHANGED
|
@@ -1,14 +1,34 @@
|
|
|
1
1
|
import { nanoid } from "nanoid";
|
|
2
2
|
import { GROOVEBOX_BUILD } from "./groovebox_build.js";
|
|
3
3
|
|
|
4
|
-
let
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
let workers = {};
|
|
5
|
+
let parents = {};
|
|
6
|
+
|
|
7
|
+
function terminateAll() {
|
|
8
|
+
for (let [vmID, worker] of Object.entries(workers)) {
|
|
9
|
+
worker.terminate();
|
|
10
|
+
};
|
|
11
|
+
workers = {};
|
|
12
|
+
parents = {};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function terminateVM(vmID) {
|
|
16
|
+
let worker = workers[vmID];
|
|
17
|
+
if (worker) {
|
|
18
|
+
delete workers[vmID];
|
|
19
|
+
delete parents[vmID];
|
|
20
|
+
worker.terminate();
|
|
21
|
+
for (let [subID, parentID] of Object.entries(parents)) {
|
|
22
|
+
terminateVM(subID);
|
|
23
|
+
};
|
|
11
24
|
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (globalThis.ThisIsNode) {
|
|
28
|
+
Process.on("exit", () => {
|
|
29
|
+
console.log("terminating machine workers");
|
|
30
|
+
terminateAll()
|
|
31
|
+
})
|
|
12
32
|
};
|
|
13
33
|
|
|
14
34
|
function CreateVMID() {
|
|
@@ -16,8 +36,14 @@ function CreateVMID() {
|
|
|
16
36
|
}
|
|
17
37
|
|
|
18
38
|
let initialMask = 64 + 1024; // default for web
|
|
39
|
+
|
|
19
40
|
globalThis.MixSetMask = (m => {
|
|
20
41
|
initialMask = m;
|
|
42
|
+
for (let [vmID, worker] of Object.entries(workers)) {
|
|
43
|
+
worker.postMessage({ "_rmx_type": "msg_vm_logMask",
|
|
44
|
+
"mask": m
|
|
45
|
+
})
|
|
46
|
+
}
|
|
21
47
|
});
|
|
22
48
|
|
|
23
49
|
function StartWASM(hub, baseURL, org, workspace, vmID, user, token, noOutputViaMQTT) {
|
|
@@ -51,20 +77,29 @@ function StartWASM2(hub, config) {
|
|
|
51
77
|
fetch(code_url, {cache:"default"}).then(resp => { return resp.arrayBuffer() });
|
|
52
78
|
bundle = new URL("/g/machine-wasm-core.js", window.location.href);
|
|
53
79
|
}
|
|
54
|
-
let
|
|
80
|
+
let localFFIkind = {};
|
|
81
|
+
let localFFIfuns = {};
|
|
55
82
|
if (config.localFFIs) {
|
|
56
83
|
for (const [k, v] of Object.entries(config.localFFIs)) {
|
|
84
|
+
localFFIfuns[k] = {...v};
|
|
57
85
|
if (v.isRaw && (v.canFail || v.useJsonDecoder)) {
|
|
58
86
|
console.error("A raw, local FFI must neither be failing nor use the JSON decoder: " + k);
|
|
59
87
|
} else {
|
|
60
|
-
|
|
61
|
-
delete
|
|
88
|
+
localFFIkind[k] = {...v};
|
|
89
|
+
delete localFFIkind[k].run;
|
|
62
90
|
}
|
|
63
|
-
}
|
|
91
|
+
};
|
|
92
|
+
let vm_kind = { isRaw:false, canFail:false, useJsonDecoder:false};
|
|
93
|
+
localFFIkind["$vm_start"] = vm_kind;
|
|
94
|
+
localFFIfuns["$vm_start"] = ffi_vm_start;
|
|
95
|
+
localFFIkind["$vm_stop"] = vm_kind;
|
|
96
|
+
localFFIfuns["$vm_stop"] = ffi_vm_stop;
|
|
64
97
|
}
|
|
65
98
|
let worker = new Worker(bundle);
|
|
99
|
+
workers[config.vmID] = worker;
|
|
66
100
|
let config_msg =
|
|
67
101
|
{ "_rmx_type": "msg_vm_configure",
|
|
102
|
+
"workerURL": bundle.toString(),
|
|
68
103
|
"baseURL": config.baseURL,
|
|
69
104
|
"org": config.org,
|
|
70
105
|
"workspace": config.workspace,
|
|
@@ -75,23 +110,47 @@ function StartWASM2(hub, config) {
|
|
|
75
110
|
"outputViaMQTT": !(config.noOutputViaMQTT),
|
|
76
111
|
"machType": config.machType,
|
|
77
112
|
"debugMask": initialMask,
|
|
78
|
-
"localFFIs":
|
|
113
|
+
"localFFIs": localFFIkind,
|
|
79
114
|
"grooveboxUrlPrefix": globalThis.GROOVEBOX_URL_PREFIX,
|
|
80
115
|
"allowInsecureHttp": globalThis.GROOVEBOX_ALLOW_INSECURE_HTTP,
|
|
116
|
+
"jsonFFI": config.jsonFFI,
|
|
117
|
+
"interceptFFI": config.interceptFFI,
|
|
118
|
+
"interceptDynloadFFI": config.interceptDynloadFFI,
|
|
81
119
|
};
|
|
82
120
|
worker.postMessage(config_msg, [ channel.port ]);
|
|
83
|
-
terminate(() => worker.terminate());
|
|
84
|
-
globalThis.MixSetMask = (m => {
|
|
85
|
-
worker.postMessage({ "_rmx_type": "msg_vm_logMask",
|
|
86
|
-
"mask": m
|
|
87
|
-
})
|
|
88
|
-
});
|
|
89
121
|
if (config.localFFIs)
|
|
90
|
-
setupLocalFFIs(hub, config); // don't await!
|
|
122
|
+
setupLocalFFIs(hub, config, localFFIfuns); // don't await!
|
|
91
123
|
return worker;
|
|
92
124
|
})
|
|
93
125
|
}
|
|
94
126
|
|
|
127
|
+
async function ffi_vm_start(conn, args) {
|
|
128
|
+
let vm_id = "embedded." + nanoid();
|
|
129
|
+
let config = {};
|
|
130
|
+
for (const [k, v] of Object.entries(conn.config)) {
|
|
131
|
+
config[k] = v;
|
|
132
|
+
}
|
|
133
|
+
config["vmID"] = vm_id;
|
|
134
|
+
parents[vm_id] = conn.config.vmID;
|
|
135
|
+
let arg_config = args[0];
|
|
136
|
+
if (arg_config.jsonFFI !== undefined)
|
|
137
|
+
config["jsonFFI"] = arg_config.jsonFFI;
|
|
138
|
+
if (arg_config.interceptFFI !== undefined)
|
|
139
|
+
config["interceptFFI"] = arg_config.interceptFFI;
|
|
140
|
+
if (arg_config.interceptDynloadFFI !== undefined)
|
|
141
|
+
config["interceptDynloadFFI"] = arg_config.interceptDynloadFFI;
|
|
142
|
+
let worker = await StartWASM2(conn.hub, config);
|
|
143
|
+
return vm_id;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async function ffi_vm_stop(conn, args) {
|
|
147
|
+
let vm_id = args[0];
|
|
148
|
+
let worker = workers[vm_id];
|
|
149
|
+
if (!worker) throw new Error("no such VM: " + vm_id);
|
|
150
|
+
terminateVM(vm_id);
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
|
|
95
154
|
class Token {
|
|
96
155
|
constructor(data, enabled, extras) {
|
|
97
156
|
// data: must be an Uint8Array
|
|
@@ -207,13 +266,13 @@ function decode(val) {
|
|
|
207
266
|
}
|
|
208
267
|
}
|
|
209
268
|
|
|
210
|
-
async function setupLocalFFIs(hub, config) {
|
|
269
|
+
async function setupLocalFFIs(hub, config, localFFIs) {
|
|
270
|
+
let vmID = config.vmID;
|
|
211
271
|
let channel = await hub.newChannel();
|
|
212
|
-
let comm = new FFIComm(hub, channel);
|
|
213
|
-
|
|
214
|
-
await channel.
|
|
215
|
-
await channel.
|
|
216
|
-
let sub = await channel.subscribe("/local/ffi/call");
|
|
272
|
+
let comm = new FFIComm(vmID, hub, channel);
|
|
273
|
+
await channel.setLocalSubTopic("/local/" + vmID);
|
|
274
|
+
await channel.setLocalPubTopic("/local/" + vmID);
|
|
275
|
+
let sub = await channel.subscribe("/local/" + vmID + "/ffi/call");
|
|
217
276
|
while (true) {
|
|
218
277
|
let msg = await sub.next();
|
|
219
278
|
let name = msg.payload.name;
|
|
@@ -227,14 +286,15 @@ async function setupLocalFFIs(hub, config) {
|
|
|
227
286
|
{ call_id: call_id,
|
|
228
287
|
hub: hub,
|
|
229
288
|
channel: channel,
|
|
289
|
+
config: config,
|
|
230
290
|
state: config.state,
|
|
231
291
|
};
|
|
232
292
|
let r = fun instanceof Function ? fun(connector, args) : fun.run(connector, args);
|
|
233
293
|
if (r instanceof Promise) {
|
|
294
|
+
r.catch(_ => null); // prevent "unhandled rejection"
|
|
234
295
|
await comm.later(call_id);
|
|
235
|
-
r
|
|
236
|
-
|
|
237
|
-
(reason) => comm.error(call_id, reason.message, reason.stack));
|
|
296
|
+
let value = await r;
|
|
297
|
+
await comm.returnOrFail(fun, call_id, value);
|
|
238
298
|
} else {
|
|
239
299
|
await comm.returnOrFail(fun, call_id, r);
|
|
240
300
|
}
|
|
@@ -245,7 +305,8 @@ async function setupLocalFFIs(hub, config) {
|
|
|
245
305
|
}
|
|
246
306
|
|
|
247
307
|
class FFIComm {
|
|
248
|
-
constructor(hub, channel) {
|
|
308
|
+
constructor(vmID, hub, channel) {
|
|
309
|
+
this.vmID = vmID;
|
|
249
310
|
this.hub = hub;
|
|
250
311
|
this.channel = channel;
|
|
251
312
|
}
|
|
@@ -254,7 +315,7 @@ class FFIComm {
|
|
|
254
315
|
{ call_id: call_id,
|
|
255
316
|
};
|
|
256
317
|
let response = this.hub.newLocalMessage("msg_ffi_later", "starter", r_payload);
|
|
257
|
-
return this.channel.publish("/local/ffi/return", response, false);
|
|
318
|
+
return this.channel.publish("/local/" + this.vmID + "/ffi/return", response, false);
|
|
258
319
|
}
|
|
259
320
|
return_(fun, call_id, result) {
|
|
260
321
|
let r_payload =
|
|
@@ -262,7 +323,7 @@ class FFIComm {
|
|
|
262
323
|
value: fun.useJsonDecoder ? result : encode(result)
|
|
263
324
|
};
|
|
264
325
|
let response = this.hub.newLocalMessage("msg_ffi_return", "starter", r_payload);
|
|
265
|
-
return this.channel.publish("/local/ffi/return", response, false);
|
|
326
|
+
return this.channel.publish("/local/" + this.vmID + "/ffi/return", response, false);
|
|
266
327
|
}
|
|
267
328
|
error(call_id, message, stack) {
|
|
268
329
|
let r_payload =
|
|
@@ -271,7 +332,7 @@ class FFIComm {
|
|
|
271
332
|
stack: stack === undefined ? [] : stack,
|
|
272
333
|
};
|
|
273
334
|
let response = this.hub.newLocalMessage("msg_ffi_error", "starter", r_payload);
|
|
274
|
-
this.channel.publish("/local/ffi/return", response, false);
|
|
335
|
+
this.channel.publish("/local/" + this.vmID + "/ffi/return", response, false);
|
|
275
336
|
}
|
|
276
337
|
returnOrFail(fun, call_id, result) {
|
|
277
338
|
if (fun.canFail) {
|
|
@@ -302,5 +363,6 @@ class FFIComm {
|
|
|
302
363
|
// use worker.terminate() to shut a worker down!
|
|
303
364
|
|
|
304
365
|
export { CreateVMID, StartWASM, StartWASM2,
|
|
366
|
+
terminateAll, terminateVM,
|
|
305
367
|
Token, Case, Opaque
|
|
306
368
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remix_labs/machine-starter",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1466.0-dev",
|
|
4
4
|
"description": "start the groove",
|
|
5
5
|
"main": "node.js",
|
|
6
6
|
"browser": "index.js",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"author": "Remixlabs staff",
|
|
12
12
|
"license": "ISC",
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@remix_labs/hub-client": "1.
|
|
14
|
+
"@remix_labs/hub-client": "1.1466.0-dev",
|
|
15
15
|
"nanoid": "^3.1.12",
|
|
16
16
|
"web-worker": "^1.2.0"
|
|
17
17
|
},
|
package/start.js
CHANGED