@remix_labs/machine-starter 2.1995.0-dev → 2.1999.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/common.js CHANGED
@@ -1,18 +1,45 @@
1
1
  import { GROOVEBOX_BUILD } from "./groovebox_build.js";
2
+ import { nanoid } from "nanoid";
2
3
 
3
- let terminate = function(f) {};
4
- if (globalThis.ThisIsNode) {
5
- terminate = function(f) {
6
- Process.on("exit", () => {
7
- console.log("terminating machine worker");
8
- f()
9
- })
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
+ };
10
24
  }
25
+ }
26
+
27
+ if (globalThis.Process) {
28
+ Process.on("exit", () => {
29
+ console.log("terminating machine workers");
30
+ terminateAll()
31
+ })
11
32
  };
12
33
 
13
34
  let initialMask = 64 + 1024; // default for web
35
+
14
36
  globalThis.MixSetMask = (m => {
15
37
  initialMask = m;
38
+ for (let [vmID, worker] of Object.entries(workers)) {
39
+ worker.postMessage({ "_rmx_type": "msg_vm_logMask",
40
+ "mask": m
41
+ })
42
+ }
16
43
  });
17
44
 
18
45
  function StartWASM(hub, baseURL, org, workspace, vmID, user, token, noOutputViaMQTT) {
@@ -31,16 +58,24 @@ function StartWASM2(hub, config) {
31
58
  return hub.newChannel().then(channel => {
32
59
  // injected by either index.js or node.js
33
60
  let worker = globalThis.GetMachineWASMWorker();
34
- let localFFIs = {};
61
+ workers[config.vmID] = worker;
62
+ let localFFIkind = {};
63
+ let localFFIfuns = {};
35
64
  if (config.localFFIs) {
36
65
  for (const [k, v] of Object.entries(config.localFFIs)) {
66
+ localFFIfuns[k] = {...v};
37
67
  if (v.isRaw && (v.canFail || v.useJsonDecoder)) {
38
68
  console.error("A raw, local FFI must neither be failing nor use the JSON decoder: " + k);
39
69
  } else {
40
- localFFIs[k] = {...v};
41
- delete localFFIs[k].run;
70
+ localFFIkind[k] = {...v};
71
+ delete localFFIkind[k].run;
42
72
  }
43
- }
73
+ };
74
+ let vm_kind = { isRaw:false, canFail:false, useJsonDecoder:false};
75
+ localFFIkind["$vm_start"] = vm_kind;
76
+ localFFIfuns["$vm_start"] = ffi_vm_start;
77
+ localFFIkind["$vm_stop"] = vm_kind;
78
+ localFFIfuns["$vm_stop"] = ffi_vm_stop;
44
79
  }
45
80
  let config_msg =
46
81
  { "_rmx_type": "msg_vm_configure",
@@ -54,24 +89,43 @@ function StartWASM2(hub, config) {
54
89
  "outputViaMQTT": !(config.noOutputViaMQTT),
55
90
  "machType": config.machType,
56
91
  "debugMask": initialMask,
57
- "localFFIs": localFFIs,
92
+ "localFFIs": localFFIkind,
58
93
  "allowInsecureHttp": globalThis.GROOVEBOX_ALLOW_INSECURE_HTTP,
59
94
  "interceptFFI": config.interceptFFI,
60
95
  "interceptDynloadFFI": config.interceptDynloadFFI,
61
96
  };
62
97
  worker.postMessage(config_msg, [ channel.port ]);
63
- terminate(() => worker.terminate());
64
- globalThis.MixSetMask = (m => {
65
- worker.postMessage({ "_rmx_type": "msg_vm_logMask",
66
- "mask": m
67
- })
68
- });
69
98
  if (config.localFFIs)
70
- setupLocalFFIs(hub, config); // don't await!
99
+ setupLocalFFIs(hub, config, localFFIfuns); // don't await!
71
100
  return worker;
72
101
  })
73
102
  }
74
103
 
104
+ async function ffi_vm_start(conn, args) {
105
+ let vm_id = "embedded." + nanoid();
106
+ let config = {};
107
+ for (const [k, v] of Object.entries(conn.config)) {
108
+ config[k] = v;
109
+ }
110
+ config["vmID"] = vm_id;
111
+ parents[vm_id] = conn.config.vmID;
112
+ let arg_config = args[0];
113
+ if (arg_config.interceptFFI !== undefined)
114
+ config["interceptFFI"] = arg_config.interceptFFI;
115
+ if (arg_config.interceptDynloadFFI !== undefined)
116
+ config["interceptDynloadFFI"] = arg_config.interceptDynloadFFI;
117
+ let worker = await StartWASM2(conn.hub, config);
118
+ return vm_id;
119
+ }
120
+
121
+ async function ffi_vm_stop(conn, args) {
122
+ let vm_id = args[0];
123
+ let worker = workers[vm_id];
124
+ if (!worker) throw new Error("no such VM: " + vm_id);
125
+ terminateVM(vm_id);
126
+ return null;
127
+ }
128
+
75
129
  class Token {
76
130
  constructor(data, enabled, extras) {
77
131
  // data: must be an Uint8Array
@@ -187,13 +241,13 @@ function decode(val) {
187
241
  }
188
242
  }
189
243
 
190
- async function setupLocalFFIs(hub, config) {
244
+ async function setupLocalFFIs(hub, config, localFFIs) {
245
+ let vmID = config.vmID;
191
246
  let channel = await hub.newChannel();
192
- let comm = new FFIComm(hub, channel);
193
- let localFFIs = config.localFFIs;
194
- await channel.setLocalSubTopic("/local/ffi/call");
195
- await channel.setLocalPubTopic("/local/ffi/return");
196
- let sub = await channel.subscribe("/local/ffi/call");
247
+ let comm = new FFIComm(vmID, hub, channel);
248
+ await channel.setLocalSubTopic("/local/" + vmID);
249
+ await channel.setLocalPubTopic("/local/" + vmID);
250
+ let sub = await channel.subscribe("/local/" + vmID + "/ffi/call");
197
251
  while (true) {
198
252
  let msg = await sub.next();
199
253
  let name = msg.payload.name;
@@ -207,14 +261,15 @@ async function setupLocalFFIs(hub, config) {
207
261
  { call_id: call_id,
208
262
  hub: hub,
209
263
  channel: channel,
264
+ config: config,
210
265
  state: config.state,
211
266
  };
212
267
  let r = fun instanceof Function ? fun(connector, args) : fun.run(connector, args);
213
268
  if (r instanceof Promise) {
269
+ // r.catch(_ => null); // prevent "unhandled rejection"
214
270
  await comm.later(call_id);
215
- r.then(
216
- (value) => comm.returnOrFail(fun, call_id, value),
217
- (reason) => comm.error(call_id, reason.message, reason.stack));
271
+ let value = await r;
272
+ await comm.returnOrFail(fun, call_id, value);
218
273
  } else {
219
274
  await comm.returnOrFail(fun, call_id, r);
220
275
  }
@@ -225,7 +280,8 @@ async function setupLocalFFIs(hub, config) {
225
280
  }
226
281
 
227
282
  class FFIComm {
228
- constructor(hub, channel) {
283
+ constructor(vmID, hub, channel) {
284
+ this.vmID = vmID;
229
285
  this.hub = hub;
230
286
  this.channel = channel;
231
287
  }
@@ -234,7 +290,7 @@ class FFIComm {
234
290
  { call_id: call_id,
235
291
  };
236
292
  let response = this.hub.newLocalMessage("msg_ffi_later", "starter", r_payload);
237
- return this.channel.publish("/local/ffi/return", response, false);
293
+ return this.channel.publish("/local/" + this.vmID + "/ffi/return", response, false);
238
294
  }
239
295
  return_(fun, call_id, result) {
240
296
  let r_payload =
@@ -242,7 +298,7 @@ class FFIComm {
242
298
  value: fun.useJsonDecoder ? result : encode(result)
243
299
  };
244
300
  let response = this.hub.newLocalMessage("msg_ffi_return", "starter", r_payload);
245
- return this.channel.publish("/local/ffi/return", response, false);
301
+ return this.channel.publish("/local/" + this.vmID + "/ffi/return", response, false);
246
302
  }
247
303
  error(call_id, message, stack) {
248
304
  let r_payload =
@@ -251,7 +307,7 @@ class FFIComm {
251
307
  stack: stack === undefined ? [] : stack,
252
308
  };
253
309
  let response = this.hub.newLocalMessage("msg_ffi_error", "starter", r_payload);
254
- this.channel.publish("/local/ffi/return", response, false);
310
+ this.channel.publish("/local/" + this.vmID + "/ffi/return", response, false);
255
311
  }
256
312
  returnOrFail(fun, call_id, result) {
257
313
  if (fun.canFail) {
@@ -281,4 +337,6 @@ class FFIComm {
281
337
 
282
338
  // use worker.terminate() to shut a worker down!
283
339
 
284
- export { StartWASM, StartWASM2, Token, Case, Opaque }
340
+ export { StartWASM, StartWASM2, terminateAll, terminateVM,
341
+ Token, Case, Opaque
342
+ }
@@ -1,2 +1,2 @@
1
- var GROOVEBOX_BUILD = "2124";
1
+ var GROOVEBOX_BUILD = "2129";
2
2
  export { GROOVEBOX_BUILD }
package/index.js CHANGED
@@ -17,4 +17,3 @@ function GetMachineWASMWorker() {
17
17
  globalThis.GetMachineWASMWorker = GetMachineWASMWorker;
18
18
 
19
19
  export * from './common.js';
20
-