@remix_labs/machine-starter 1.1863.0-dev → 1.1868.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 +89 -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 = "1868";
|
|
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,25 +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,
|
|
81
116
|
"interceptFFI": config.interceptFFI,
|
|
82
117
|
"interceptDynloadFFI": config.interceptDynloadFFI,
|
|
83
118
|
};
|
|
84
119
|
worker.postMessage(config_msg, [ channel.port ]);
|
|
85
|
-
terminate(() => worker.terminate());
|
|
86
|
-
globalThis.MixSetMask = (m => {
|
|
87
|
-
worker.postMessage({ "_rmx_type": "msg_vm_logMask",
|
|
88
|
-
"mask": m
|
|
89
|
-
})
|
|
90
|
-
});
|
|
91
120
|
if (config.localFFIs)
|
|
92
|
-
setupLocalFFIs(hub, config); // don't await!
|
|
121
|
+
setupLocalFFIs(hub, config, localFFIfuns); // don't await!
|
|
93
122
|
return worker;
|
|
94
123
|
})
|
|
95
124
|
}
|
|
96
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
|
+
|
|
97
151
|
class Token {
|
|
98
152
|
constructor(data, enabled, extras) {
|
|
99
153
|
// data: must be an Uint8Array
|
|
@@ -209,13 +263,13 @@ function decode(val) {
|
|
|
209
263
|
}
|
|
210
264
|
}
|
|
211
265
|
|
|
212
|
-
async function setupLocalFFIs(hub, config) {
|
|
266
|
+
async function setupLocalFFIs(hub, config, localFFIs) {
|
|
267
|
+
let vmID = config.vmID;
|
|
213
268
|
let channel = await hub.newChannel();
|
|
214
|
-
let comm = new FFIComm(hub, channel);
|
|
215
|
-
|
|
216
|
-
await channel.
|
|
217
|
-
await channel.
|
|
218
|
-
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");
|
|
219
273
|
while (true) {
|
|
220
274
|
let msg = await sub.next();
|
|
221
275
|
let name = msg.payload.name;
|
|
@@ -229,14 +283,15 @@ async function setupLocalFFIs(hub, config) {
|
|
|
229
283
|
{ call_id: call_id,
|
|
230
284
|
hub: hub,
|
|
231
285
|
channel: channel,
|
|
286
|
+
config: config,
|
|
232
287
|
state: config.state,
|
|
233
288
|
};
|
|
234
289
|
let r = fun instanceof Function ? fun(connector, args) : fun.run(connector, args);
|
|
235
290
|
if (r instanceof Promise) {
|
|
291
|
+
r.catch(_ => null); // prevent "unhandled rejection"
|
|
236
292
|
await comm.later(call_id);
|
|
237
|
-
r
|
|
238
|
-
|
|
239
|
-
(reason) => comm.error(call_id, reason.message, reason.stack));
|
|
293
|
+
let value = await r;
|
|
294
|
+
await comm.returnOrFail(fun, call_id, value);
|
|
240
295
|
} else {
|
|
241
296
|
await comm.returnOrFail(fun, call_id, r);
|
|
242
297
|
}
|
|
@@ -247,7 +302,8 @@ async function setupLocalFFIs(hub, config) {
|
|
|
247
302
|
}
|
|
248
303
|
|
|
249
304
|
class FFIComm {
|
|
250
|
-
constructor(hub, channel) {
|
|
305
|
+
constructor(vmID, hub, channel) {
|
|
306
|
+
this.vmID = vmID;
|
|
251
307
|
this.hub = hub;
|
|
252
308
|
this.channel = channel;
|
|
253
309
|
}
|
|
@@ -256,7 +312,7 @@ class FFIComm {
|
|
|
256
312
|
{ call_id: call_id,
|
|
257
313
|
};
|
|
258
314
|
let response = this.hub.newLocalMessage("msg_ffi_later", "starter", r_payload);
|
|
259
|
-
return this.channel.publish("/local/ffi/return", response, false);
|
|
315
|
+
return this.channel.publish("/local/" + this.vmID + "/ffi/return", response, false);
|
|
260
316
|
}
|
|
261
317
|
return_(fun, call_id, result) {
|
|
262
318
|
let r_payload =
|
|
@@ -264,7 +320,7 @@ class FFIComm {
|
|
|
264
320
|
value: fun.useJsonDecoder ? result : encode(result)
|
|
265
321
|
};
|
|
266
322
|
let response = this.hub.newLocalMessage("msg_ffi_return", "starter", r_payload);
|
|
267
|
-
return this.channel.publish("/local/ffi/return", response, false);
|
|
323
|
+
return this.channel.publish("/local/" + this.vmID + "/ffi/return", response, false);
|
|
268
324
|
}
|
|
269
325
|
error(call_id, message, stack) {
|
|
270
326
|
let r_payload =
|
|
@@ -273,7 +329,7 @@ class FFIComm {
|
|
|
273
329
|
stack: stack === undefined ? [] : stack,
|
|
274
330
|
};
|
|
275
331
|
let response = this.hub.newLocalMessage("msg_ffi_error", "starter", r_payload);
|
|
276
|
-
this.channel.publish("/local/ffi/return", response, false);
|
|
332
|
+
this.channel.publish("/local/" + this.vmID + "/ffi/return", response, false);
|
|
277
333
|
}
|
|
278
334
|
returnOrFail(fun, call_id, result) {
|
|
279
335
|
if (fun.canFail) {
|
|
@@ -304,5 +360,6 @@ class FFIComm {
|
|
|
304
360
|
// use worker.terminate() to shut a worker down!
|
|
305
361
|
|
|
306
362
|
export { CreateVMID, StartWASM, StartWASM2,
|
|
363
|
+
terminateAll, terminateVM,
|
|
307
364
|
Token, Case, Opaque
|
|
308
365
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remix_labs/machine-starter",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1868.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.1868.0-dev",
|
|
15
15
|
"nanoid": "^3.1.12",
|
|
16
16
|
"web-worker": "^1.2.0"
|
|
17
17
|
},
|
package/start.js
CHANGED