@remix_labs/machine-starter 1.1781.0-dev → 1.1791.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/groovebox_build.js +1 -1
- package/index.js +91 -32
- package/package.json +2 -2
- package/start.js +2 -1
package/groovebox_build.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var GROOVEBOX_BUILD = "
|
|
1
|
+
var GROOVEBOX_BUILD = "1791";
|
|
2
2
|
export { GROOVEBOX_BUILD }
|
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,44 @@ 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
|
+
"interceptFFI": config.interceptFFI,
|
|
117
|
+
"interceptDynloadFFI": config.interceptDynloadFFI,
|
|
81
118
|
};
|
|
82
119
|
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
120
|
if (config.localFFIs)
|
|
90
|
-
setupLocalFFIs(hub, config); // don't await!
|
|
121
|
+
setupLocalFFIs(hub, config, localFFIfuns); // don't await!
|
|
91
122
|
return worker;
|
|
92
123
|
})
|
|
93
124
|
}
|
|
94
125
|
|
|
126
|
+
async function ffi_vm_start(conn, args) {
|
|
127
|
+
let vm_id = "embedded." + nanoid();
|
|
128
|
+
let config = {};
|
|
129
|
+
for (const [k, v] of Object.entries(conn.config)) {
|
|
130
|
+
config[k] = v;
|
|
131
|
+
}
|
|
132
|
+
config["vmID"] = vm_id;
|
|
133
|
+
parents[vm_id] = conn.config.vmID;
|
|
134
|
+
let arg_config = args[0];
|
|
135
|
+
if (arg_config.interceptFFI !== undefined)
|
|
136
|
+
config["interceptFFI"] = arg_config.interceptFFI;
|
|
137
|
+
if (arg_config.interceptDynloadFFI !== undefined)
|
|
138
|
+
config["interceptDynloadFFI"] = arg_config.interceptDynloadFFI;
|
|
139
|
+
let worker = await StartWASM2(conn.hub, config);
|
|
140
|
+
return vm_id;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async function ffi_vm_stop(conn, args) {
|
|
144
|
+
let vm_id = args[0];
|
|
145
|
+
let worker = workers[vm_id];
|
|
146
|
+
if (!worker) throw new Error("no such VM: " + vm_id);
|
|
147
|
+
terminateVM(vm_id);
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
|
|
95
151
|
class Token {
|
|
96
152
|
constructor(data, enabled, extras) {
|
|
97
153
|
// data: must be an Uint8Array
|
|
@@ -207,13 +263,13 @@ function decode(val) {
|
|
|
207
263
|
}
|
|
208
264
|
}
|
|
209
265
|
|
|
210
|
-
async function setupLocalFFIs(hub, config) {
|
|
266
|
+
async function setupLocalFFIs(hub, config, localFFIs) {
|
|
267
|
+
let vmID = config.vmID;
|
|
211
268
|
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");
|
|
269
|
+
let comm = new FFIComm(vmID, hub, channel);
|
|
270
|
+
await channel.setLocalSubTopic("/local/" + vmID);
|
|
271
|
+
await channel.setLocalPubTopic("/local/" + vmID);
|
|
272
|
+
let sub = await channel.subscribe("/local/" + vmID + "/ffi/call");
|
|
217
273
|
while (true) {
|
|
218
274
|
let msg = await sub.next();
|
|
219
275
|
let name = msg.payload.name;
|
|
@@ -227,14 +283,15 @@ async function setupLocalFFIs(hub, config) {
|
|
|
227
283
|
{ call_id: call_id,
|
|
228
284
|
hub: hub,
|
|
229
285
|
channel: channel,
|
|
286
|
+
config: config,
|
|
230
287
|
state: config.state,
|
|
231
288
|
};
|
|
232
289
|
let r = fun instanceof Function ? fun(connector, args) : fun.run(connector, args);
|
|
233
290
|
if (r instanceof Promise) {
|
|
291
|
+
r.catch(_ => null); // prevent "unhandled rejection"
|
|
234
292
|
await comm.later(call_id);
|
|
235
|
-
r
|
|
236
|
-
|
|
237
|
-
(reason) => comm.error(call_id, reason.message, reason.stack));
|
|
293
|
+
let value = await r;
|
|
294
|
+
await comm.returnOrFail(fun, call_id, value);
|
|
238
295
|
} else {
|
|
239
296
|
await comm.returnOrFail(fun, call_id, r);
|
|
240
297
|
}
|
|
@@ -245,7 +302,8 @@ async function setupLocalFFIs(hub, config) {
|
|
|
245
302
|
}
|
|
246
303
|
|
|
247
304
|
class FFIComm {
|
|
248
|
-
constructor(hub, channel) {
|
|
305
|
+
constructor(vmID, hub, channel) {
|
|
306
|
+
this.vmID = vmID;
|
|
249
307
|
this.hub = hub;
|
|
250
308
|
this.channel = channel;
|
|
251
309
|
}
|
|
@@ -254,7 +312,7 @@ class FFIComm {
|
|
|
254
312
|
{ call_id: call_id,
|
|
255
313
|
};
|
|
256
314
|
let response = this.hub.newLocalMessage("msg_ffi_later", "starter", r_payload);
|
|
257
|
-
return this.channel.publish("/local/ffi/return", response, false);
|
|
315
|
+
return this.channel.publish("/local/" + this.vmID + "/ffi/return", response, false);
|
|
258
316
|
}
|
|
259
317
|
return_(fun, call_id, result) {
|
|
260
318
|
let r_payload =
|
|
@@ -262,7 +320,7 @@ class FFIComm {
|
|
|
262
320
|
value: fun.useJsonDecoder ? result : encode(result)
|
|
263
321
|
};
|
|
264
322
|
let response = this.hub.newLocalMessage("msg_ffi_return", "starter", r_payload);
|
|
265
|
-
return this.channel.publish("/local/ffi/return", response, false);
|
|
323
|
+
return this.channel.publish("/local/" + this.vmID + "/ffi/return", response, false);
|
|
266
324
|
}
|
|
267
325
|
error(call_id, message, stack) {
|
|
268
326
|
let r_payload =
|
|
@@ -271,7 +329,7 @@ class FFIComm {
|
|
|
271
329
|
stack: stack === undefined ? [] : stack,
|
|
272
330
|
};
|
|
273
331
|
let response = this.hub.newLocalMessage("msg_ffi_error", "starter", r_payload);
|
|
274
|
-
this.channel.publish("/local/ffi/return", response, false);
|
|
332
|
+
this.channel.publish("/local/" + this.vmID + "/ffi/return", response, false);
|
|
275
333
|
}
|
|
276
334
|
returnOrFail(fun, call_id, result) {
|
|
277
335
|
if (fun.canFail) {
|
|
@@ -302,5 +360,6 @@ class FFIComm {
|
|
|
302
360
|
// use worker.terminate() to shut a worker down!
|
|
303
361
|
|
|
304
362
|
export { CreateVMID, StartWASM, StartWASM2,
|
|
363
|
+
terminateAll, terminateVM,
|
|
305
364
|
Token, Case, Opaque
|
|
306
365
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remix_labs/machine-starter",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1791.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.1791.0-dev",
|
|
15
15
|
"nanoid": "^3.1.12",
|
|
16
16
|
"web-worker": "^1.2.0"
|
|
17
17
|
},
|
package/start.js
CHANGED