@remix_labs/machine-starter 1.1872.0-dev → 1.1878.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 +51 -102
- package/node.js +47 -5
- package/package.json +2 -2
- package/{start.js → start.mjs} +11 -4
- package/webpack.config.js +39 -0
package/groovebox_build.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var GROOVEBOX_BUILD = "
|
|
1
|
+
var GROOVEBOX_BUILD = "1878";
|
|
2
2
|
export { GROOVEBOX_BUILD }
|
package/index.js
CHANGED
|
@@ -1,34 +1,14 @@
|
|
|
1
1
|
import { nanoid } from "nanoid";
|
|
2
2
|
import { GROOVEBOX_BUILD } from "./groovebox_build.js";
|
|
3
3
|
|
|
4
|
-
let
|
|
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
|
-
};
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
4
|
+
let terminate = function(f) {};
|
|
27
5
|
if (globalThis.ThisIsNode) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
6
|
+
terminate = function(f) {
|
|
7
|
+
Process.on("exit", () => {
|
|
8
|
+
console.log("terminating machine worker");
|
|
9
|
+
f()
|
|
10
|
+
})
|
|
11
|
+
}
|
|
32
12
|
};
|
|
33
13
|
|
|
34
14
|
function CreateVMID() {
|
|
@@ -36,14 +16,8 @@ function CreateVMID() {
|
|
|
36
16
|
}
|
|
37
17
|
|
|
38
18
|
let initialMask = 64 + 1024; // default for web
|
|
39
|
-
|
|
40
19
|
globalThis.MixSetMask = (m => {
|
|
41
20
|
initialMask = m;
|
|
42
|
-
for (let [vmID, worker] of Object.entries(workers)) {
|
|
43
|
-
worker.postMessage({ "_rmx_type": "msg_vm_logMask",
|
|
44
|
-
"mask": m
|
|
45
|
-
})
|
|
46
|
-
}
|
|
47
21
|
});
|
|
48
22
|
|
|
49
23
|
function StartWASM(hub, baseURL, org, workspace, vmID, user, token, noOutputViaMQTT) {
|
|
@@ -62,44 +36,41 @@ function StartWASM(hub, baseURL, org, workspace, vmID, user, token, noOutputViaM
|
|
|
62
36
|
function StartWASM2(hub, config) {
|
|
63
37
|
console.log("GROOVEBOX_BUILD (machine-starter)", GROOVEBOX_BUILD);
|
|
64
38
|
return hub.newChannel().then(channel => {
|
|
65
|
-
let
|
|
39
|
+
let worker;
|
|
66
40
|
if (globalThis.ThisIsNode) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
// already fire off the download of the wasm code:
|
|
71
|
-
let code_url = new URL(`${globalThis.GROOVEBOX_URL_PREFIX}/machine-wasm-code.wasm`, window.location.href);
|
|
72
|
-
fetch(code_url, {cache:"default"}).then(resp => { return resp.arrayBuffer() });
|
|
73
|
-
bundle = new URL(`${globalThis.GROOVEBOX_URL_PREFIX}/machine-wasm-core.js`, window.location.href);
|
|
41
|
+
console.log("loading node bundle")
|
|
42
|
+
//bundle = new URL("file:///Users/verm/remix/harmony/components/groovebox/machine-wasm/dist/node-bundle.js");
|
|
43
|
+
worker = globalThis.getMachineWasmWorker();
|
|
74
44
|
} else {
|
|
75
|
-
|
|
76
|
-
let
|
|
77
|
-
|
|
78
|
-
|
|
45
|
+
console.log("non-node bundle");
|
|
46
|
+
let bundle;
|
|
47
|
+
if (globalThis.GROOVEBOX_URL_PREFIX) {
|
|
48
|
+
// FIXME: Stopgap solution until we figure out a way to bundle groovebox correctly
|
|
49
|
+
// already fire off the download of the wasm code:
|
|
50
|
+
let code_url = new URL(`${globalThis.GROOVEBOX_URL_PREFIX}/machine-wasm-code.wasm`, window.location.href);
|
|
51
|
+
fetch(code_url, {cache:"default"}).then(resp => { return resp.arrayBuffer() });
|
|
52
|
+
bundle = new URL(`${globalThis.GROOVEBOX_URL_PREFIX}/machine-wasm.js`, window.location.href);
|
|
53
|
+
} else {
|
|
54
|
+
// already fire off the download of the wasm code:
|
|
55
|
+
let code_url = new URL("/g/machine-wasm-code.wasm", window.location.href);
|
|
56
|
+
fetch(code_url, {cache:"default"}).then(resp => { return resp.arrayBuffer() });
|
|
57
|
+
bundle = new URL("/g/machine-wasm.js", window.location.href);
|
|
58
|
+
}
|
|
59
|
+
worker = new Worker(bundle);
|
|
79
60
|
}
|
|
80
|
-
let
|
|
81
|
-
let localFFIfuns = {};
|
|
61
|
+
let localFFIs = {};
|
|
82
62
|
if (config.localFFIs) {
|
|
83
63
|
for (const [k, v] of Object.entries(config.localFFIs)) {
|
|
84
|
-
localFFIfuns[k] = {...v};
|
|
85
64
|
if (v.isRaw && (v.canFail || v.useJsonDecoder)) {
|
|
86
65
|
console.error("A raw, local FFI must neither be failing nor use the JSON decoder: " + k);
|
|
87
66
|
} else {
|
|
88
|
-
|
|
89
|
-
delete
|
|
67
|
+
localFFIs[k] = {...v};
|
|
68
|
+
delete localFFIs[k].run;
|
|
90
69
|
}
|
|
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;
|
|
70
|
+
}
|
|
97
71
|
}
|
|
98
|
-
let worker = new Worker(bundle);
|
|
99
|
-
workers[config.vmID] = worker;
|
|
100
72
|
let config_msg =
|
|
101
73
|
{ "_rmx_type": "msg_vm_configure",
|
|
102
|
-
"workerURL": bundle.toString(),
|
|
103
74
|
"baseURL": config.baseURL,
|
|
104
75
|
"org": config.org,
|
|
105
76
|
"workspace": config.workspace,
|
|
@@ -110,44 +81,25 @@ function StartWASM2(hub, config) {
|
|
|
110
81
|
"outputViaMQTT": !(config.noOutputViaMQTT),
|
|
111
82
|
"machType": config.machType,
|
|
112
83
|
"debugMask": initialMask,
|
|
113
|
-
"localFFIs":
|
|
84
|
+
"localFFIs": localFFIs,
|
|
114
85
|
"grooveboxUrlPrefix": globalThis.GROOVEBOX_URL_PREFIX,
|
|
115
86
|
"allowInsecureHttp": globalThis.GROOVEBOX_ALLOW_INSECURE_HTTP,
|
|
116
87
|
"interceptFFI": config.interceptFFI,
|
|
117
88
|
"interceptDynloadFFI": config.interceptDynloadFFI,
|
|
118
89
|
};
|
|
119
90
|
worker.postMessage(config_msg, [ channel.port ]);
|
|
91
|
+
terminate(() => worker.terminate());
|
|
92
|
+
globalThis.MixSetMask = (m => {
|
|
93
|
+
worker.postMessage({ "_rmx_type": "msg_vm_logMask",
|
|
94
|
+
"mask": m
|
|
95
|
+
})
|
|
96
|
+
});
|
|
120
97
|
if (config.localFFIs)
|
|
121
|
-
setupLocalFFIs(hub, config
|
|
98
|
+
setupLocalFFIs(hub, config); // don't await!
|
|
122
99
|
return worker;
|
|
123
100
|
})
|
|
124
101
|
}
|
|
125
102
|
|
|
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
|
-
|
|
151
103
|
class Token {
|
|
152
104
|
constructor(data, enabled, extras) {
|
|
153
105
|
// data: must be an Uint8Array
|
|
@@ -263,13 +215,13 @@ function decode(val) {
|
|
|
263
215
|
}
|
|
264
216
|
}
|
|
265
217
|
|
|
266
|
-
async function setupLocalFFIs(hub, config
|
|
267
|
-
let vmID = config.vmID;
|
|
218
|
+
async function setupLocalFFIs(hub, config) {
|
|
268
219
|
let channel = await hub.newChannel();
|
|
269
|
-
let comm = new FFIComm(
|
|
270
|
-
|
|
271
|
-
await channel.
|
|
272
|
-
|
|
220
|
+
let comm = new FFIComm(hub, channel);
|
|
221
|
+
let localFFIs = config.localFFIs;
|
|
222
|
+
await channel.setLocalSubTopic("/local/ffi/call");
|
|
223
|
+
await channel.setLocalPubTopic("/local/ffi/return");
|
|
224
|
+
let sub = await channel.subscribe("/local/ffi/call");
|
|
273
225
|
while (true) {
|
|
274
226
|
let msg = await sub.next();
|
|
275
227
|
let name = msg.payload.name;
|
|
@@ -283,15 +235,14 @@ async function setupLocalFFIs(hub, config, localFFIs) {
|
|
|
283
235
|
{ call_id: call_id,
|
|
284
236
|
hub: hub,
|
|
285
237
|
channel: channel,
|
|
286
|
-
config: config,
|
|
287
238
|
state: config.state,
|
|
288
239
|
};
|
|
289
240
|
let r = fun instanceof Function ? fun(connector, args) : fun.run(connector, args);
|
|
290
241
|
if (r instanceof Promise) {
|
|
291
|
-
r.catch(_ => null); // prevent "unhandled rejection"
|
|
292
242
|
await comm.later(call_id);
|
|
293
|
-
|
|
294
|
-
|
|
243
|
+
r.then(
|
|
244
|
+
(value) => comm.returnOrFail(fun, call_id, value),
|
|
245
|
+
(reason) => comm.error(call_id, reason.message, reason.stack));
|
|
295
246
|
} else {
|
|
296
247
|
await comm.returnOrFail(fun, call_id, r);
|
|
297
248
|
}
|
|
@@ -302,8 +253,7 @@ async function setupLocalFFIs(hub, config, localFFIs) {
|
|
|
302
253
|
}
|
|
303
254
|
|
|
304
255
|
class FFIComm {
|
|
305
|
-
constructor(
|
|
306
|
-
this.vmID = vmID;
|
|
256
|
+
constructor(hub, channel) {
|
|
307
257
|
this.hub = hub;
|
|
308
258
|
this.channel = channel;
|
|
309
259
|
}
|
|
@@ -312,7 +262,7 @@ class FFIComm {
|
|
|
312
262
|
{ call_id: call_id,
|
|
313
263
|
};
|
|
314
264
|
let response = this.hub.newLocalMessage("msg_ffi_later", "starter", r_payload);
|
|
315
|
-
return this.channel.publish("/local/
|
|
265
|
+
return this.channel.publish("/local/ffi/return", response, false);
|
|
316
266
|
}
|
|
317
267
|
return_(fun, call_id, result) {
|
|
318
268
|
let r_payload =
|
|
@@ -320,7 +270,7 @@ class FFIComm {
|
|
|
320
270
|
value: fun.useJsonDecoder ? result : encode(result)
|
|
321
271
|
};
|
|
322
272
|
let response = this.hub.newLocalMessage("msg_ffi_return", "starter", r_payload);
|
|
323
|
-
return this.channel.publish("/local/
|
|
273
|
+
return this.channel.publish("/local/ffi/return", response, false);
|
|
324
274
|
}
|
|
325
275
|
error(call_id, message, stack) {
|
|
326
276
|
let r_payload =
|
|
@@ -329,7 +279,7 @@ class FFIComm {
|
|
|
329
279
|
stack: stack === undefined ? [] : stack,
|
|
330
280
|
};
|
|
331
281
|
let response = this.hub.newLocalMessage("msg_ffi_error", "starter", r_payload);
|
|
332
|
-
this.channel.publish("/local/
|
|
282
|
+
this.channel.publish("/local/ffi/return", response, false);
|
|
333
283
|
}
|
|
334
284
|
returnOrFail(fun, call_id, result) {
|
|
335
285
|
if (fun.canFail) {
|
|
@@ -360,6 +310,5 @@ class FFIComm {
|
|
|
360
310
|
// use worker.terminate() to shut a worker down!
|
|
361
311
|
|
|
362
312
|
export { CreateVMID, StartWASM, StartWASM2,
|
|
363
|
-
terminateAll, terminateVM,
|
|
364
313
|
Token, Case, Opaque
|
|
365
314
|
}
|
package/node.js
CHANGED
|
@@ -1,7 +1,49 @@
|
|
|
1
|
-
import Worker from "web-worker";
|
|
2
|
-
global.Worker = Worker;
|
|
3
|
-
import
|
|
4
|
-
global.MessageChannel =
|
|
1
|
+
//import Worker from "web-worker";
|
|
2
|
+
//global.Worker = Worker;
|
|
3
|
+
import { MessageChannel, Worker } from "worker_threads";
|
|
4
|
+
global.MessageChannel = MessageChannel;
|
|
5
5
|
import Process from "process";
|
|
6
6
|
global.Process = Process;
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
// NB: The only way I've made this work in node+webpack is if:
|
|
9
|
+
//
|
|
10
|
+
// * we use Worker from worker_threads directly
|
|
11
|
+
// * we build each worker's module with webpack as an ESM .mjs bundle
|
|
12
|
+
// * we put all the bundles in one directory
|
|
13
|
+
// * we load the worker as below with a URL('./foo.mjs')
|
|
14
|
+
//
|
|
15
|
+
// Other ways to package/load might work, but definitely seems like
|
|
16
|
+
// using worker_threads.Worker directly is needed. Webpack says ESM
|
|
17
|
+
// is necessary but I'm not sure if this is true for either the main
|
|
18
|
+
// script or the workers.
|
|
19
|
+
global.getHubWorker = () => {
|
|
20
|
+
console.log(`getting hub-worker worker`);
|
|
21
|
+
return new Worker(new URL("./hub-worker.mjs", import.meta.url))
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
global.getMachineWasmWorker = () => {
|
|
25
|
+
console.log("getting machine-wasm worker");
|
|
26
|
+
return new Worker(new URL("./machine-wasm.mjs", import.meta.url))
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
import * as Hub from "@remix_labs/hub-client";
|
|
30
|
+
|
|
31
|
+
import { fileURLToPath } from 'url';
|
|
32
|
+
global.__filename = fileURLToPath(import.meta.url);
|
|
33
|
+
|
|
34
|
+
import { CreateVMID, StartWASM, StartWASM2,
|
|
35
|
+
Token, Case, Opaque
|
|
36
|
+
} from "./index.js";
|
|
37
|
+
|
|
38
|
+
export { CreateVMID, StartWASM, StartWASM2,
|
|
39
|
+
Token, Case, Opaque, Hub
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
global.CreateVMID = CreateVMID;
|
|
43
|
+
global.StartWASM2 = StartWASM2;
|
|
44
|
+
global.StartWASM = StartWASM;
|
|
45
|
+
global.Token = Token;
|
|
46
|
+
global.Case = Case;
|
|
47
|
+
global.Opaque = Opaque;
|
|
48
|
+
global.Hub = Hub;
|
|
49
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remix_labs/machine-starter",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1878.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.1878.0-dev",
|
|
15
15
|
"nanoid": "^3.1.12",
|
|
16
16
|
"web-worker": "^1.2.0"
|
|
17
17
|
},
|
package/{start.js → start.mjs}
RENAMED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
//import { fileURLToPath } from 'url';
|
|
2
|
+
//const __filename = fileURLToPath(import.meta.url);
|
|
3
|
+
|
|
1
4
|
import Process from "process";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
5
|
+
import * as Starter from "./node.mjs";
|
|
6
|
+
//import { StartWASM2 } from "../dist/node.js";
|
|
7
|
+
//import * as Hub from "@remix_labs/hub-client";
|
|
8
|
+
|
|
9
|
+
StartWASM2 = Starter.StartWASM2;
|
|
10
|
+
Hub = Starter.Hub;
|
|
11
|
+
|
|
4
12
|
if (Process.stdout._handle)
|
|
5
13
|
Process.stdout._handle.setBlocking(true);
|
|
6
14
|
if (Process.stderr._handle)
|
|
@@ -45,8 +53,7 @@ w.configure({wsURL: mqttURL, user:mqttUser, token:mqttToken}).then(resp => {
|
|
|
45
53
|
user: mqttUser,
|
|
46
54
|
token: mqttToken,
|
|
47
55
|
noOutputViaMQTT: noOutputViaMQTT,
|
|
48
|
-
machType: variant
|
|
49
|
-
localFFIs: {},
|
|
56
|
+
machType: variant
|
|
50
57
|
});
|
|
51
58
|
break
|
|
52
59
|
default:
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
|
|
3
|
+
import {fileURLToPath} from 'url'
|
|
4
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
5
|
+
const __dirname = path.dirname(__filename);
|
|
6
|
+
|
|
7
|
+
export default [
|
|
8
|
+
{
|
|
9
|
+
target: 'node',
|
|
10
|
+
mode: "production",
|
|
11
|
+
entry: {
|
|
12
|
+
node: './node.js',
|
|
13
|
+
//'hub-worker': './hub-worker.js',
|
|
14
|
+
//'machine-wasm': './machine-wasm.js',
|
|
15
|
+
},
|
|
16
|
+
optimization: {
|
|
17
|
+
minimize: false,
|
|
18
|
+
},
|
|
19
|
+
module: {
|
|
20
|
+
rules: [
|
|
21
|
+
{
|
|
22
|
+
test: /\.js$/,
|
|
23
|
+
loader: '@open-wc/webpack-import-meta-loader'
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
experiments: {
|
|
28
|
+
outputModule: true
|
|
29
|
+
},
|
|
30
|
+
output: {
|
|
31
|
+
chunkFormat: 'module',
|
|
32
|
+
filename: '[name].mjs',
|
|
33
|
+
library : {
|
|
34
|
+
type: 'module',
|
|
35
|
+
},
|
|
36
|
+
path: path.resolve(__dirname, '../dist'),
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
]
|