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