dcp-client 5.4.0 → 5.4.2

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.
@@ -1 +1 @@
1
- {"browser":["deny-node","kvin/kvin.js","script-load-wrapper","timer-classes","wrap-event-listeners","event-loop-virtualization","lift-webgl","lift-wasm","lift-webgpu","worktimes","url","polyfills","access-lists","fetch-factory","bravojs-init","bravojs/bravo.js","bravojs-env","pyodide-core","calculate-capabilities","bootstrap"],"node":["kvin/kvin.js","sa-ww-simulation","script-load-wrapper","timer-classes","wrap-event-listeners","event-loop-virtualization","lift-webgl","lift-wasm","lift-webgpu","worktimes","url","polyfills","access-lists","fetch-factory","bravojs-init","bravojs/bravo.js","bravojs-env","pyodide-core","calculate-capabilities","bootstrap"],"native":["deny-node","kvin/kvin.js","sa-ww-simulation","script-load-wrapper","native-event-loop","timer-classes","wrap-event-listeners","event-loop-virtualization","lift-webgl","lift-wasm","lift-webgpu","worktimes","url","polyfills","access-lists","fetch-factory","bravojs-init","bravojs/bravo.js","bravojs-env","pyodide-core","calculate-capabilities","bootstrap"],"nodeTesting":["kvin/kvin.js","sa-ww-simulation","script-load-wrapper","timer-classes","wrap-event-listeners","event-loop-virtualization","lift-webgl","lift-wasm","lift-webgpu","worktimes","url","polyfills","access-lists","fetch-factory","bravojs-init","bravojs/bravo.js","bravojs-env","pyodide-core","calculate-capabilities","bootstrap","testing.js"],"testing":["deny-node","kvin/kvin.js","sa-ww-simulation","script-load-wrapper","native-event-loop","timer-classes","wrap-event-listeners","event-loop-virtualization","lift-webgl","lift-wasm","lift-webgpu","worktimes","url","polyfills","access-lists","fetch-factory","bravojs-init","bravojs/bravo.js","bravojs-env","pyodide-core","calculate-capabilities","bootstrap","testing.js"]}
1
+ {"browser":["deny-node","kvin/kvin.js","script-load-wrapper","timer-classes","wrap-event-listeners","event-loop-virtualization","lift-webgl","lift-wasm","lift-webgpu","url","polyfills","access-lists","fetch-factory","bravojs-init","bravojs/bravo.js","bravojs-env","worktimes","pyodide-core","pyodide-worktime","map-basic-worktime","calculate-capabilities","bootstrap"],"node":["kvin/kvin.js","sa-ww-simulation","script-load-wrapper","timer-classes","wrap-event-listeners","event-loop-virtualization","lift-webgl","lift-wasm","lift-webgpu","url","polyfills","access-lists","fetch-factory","bravojs-init","bravojs/bravo.js","bravojs-env","worktimes","pyodide-core","pyodide-worktime","map-basic-worktime","calculate-capabilities","bootstrap"],"native":["deny-node","kvin/kvin.js","sa-ww-simulation","script-load-wrapper","native-event-loop","timer-classes","wrap-event-listeners","event-loop-virtualization","lift-webgl","lift-wasm","lift-webgpu","url","polyfills","access-lists","fetch-factory","bravojs-init","bravojs/bravo.js","bravojs-env","worktimes","pyodide-core","pyodide-worktime","map-basic-worktime","calculate-capabilities","bootstrap"],"nodeTesting":["kvin/kvin.js","sa-ww-simulation","script-load-wrapper","timer-classes","wrap-event-listeners","event-loop-virtualization","lift-webgl","lift-wasm","lift-webgpu","url","polyfills","access-lists","fetch-factory","bravojs-init","bravojs/bravo.js","bravojs-env","worktimes","pyodide-core","pyodide-worktime","map-basic-worktime","calculate-capabilities","bootstrap","testing.js"],"testing":["deny-node","kvin/kvin.js","sa-ww-simulation","script-load-wrapper","native-event-loop","timer-classes","wrap-event-listeners","event-loop-virtualization","lift-webgl","lift-wasm","lift-webgpu","url","polyfills","access-lists","fetch-factory","bravojs-init","bravojs/bravo.js","bravojs-env","worktimes","pyodide-core","pyodide-worktime","map-basic-worktime","calculate-capabilities","bootstrap","testing.js"],"worktimes":["pyodide-worktime","map-basic-worktime"]}
@@ -0,0 +1 @@
1
+ [{"name":"map-basic","version":"1.0.0"},{"name":"pyodide","version":"0.28.0"}]
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @file generate-worktime-info.js
3
+ * Get the name and version of all worktime files in the libexec directory and export as an array.
4
+ * Worktime files are distinguished from other sandbox scripts by the sandbox-definitions.json worktimes field
5
+ *
6
+ * @author Severn Lortie <severn@distributive.network>
7
+ * @date February 2024
8
+ */
9
+
10
+ /**
11
+ * Require the sandbox scripts and extract the version and name from each worktime. Worktime setup
12
+ * scripts differentiated from normal sandbox scripts by the worktimes field in sandbox-definitions.json
13
+ * Each of these scripts expects self.wrapScriptLoading and protectedStorage to be available, so they
14
+ * are mocked as necessary.
15
+ *
16
+ * @returns {object[]} Worktime info objects ({name: String, version: String}) in descending version order
17
+ */
18
+ function getWorktimes()
19
+ {
20
+ const semver = require('semver');
21
+ const worktimeScripts = require('../generated/sandbox-definitions.json').worktimes;
22
+ const worktimes = [];
23
+ function wrapScriptLoading(_, fn)
24
+ {
25
+ fn(protectedStorage);
26
+ }
27
+ function registerWorktime(worktime)
28
+ {
29
+ worktimes.push({ name: worktime.name, version: worktime.version })
30
+ }
31
+ const protectedStorage = {};
32
+ protectedStorage.worktimes = {};
33
+ protectedStorage.worktimes.registerWorktime = registerWorktime;
34
+ globalThis.self = {};
35
+ globalThis.self.wrapScriptLoading = wrapScriptLoading;
36
+ for (const script of worktimeScripts)
37
+ require(`../libexec/sandbox/${script}`);
38
+ worktimes.sort((a, b) => semver.compare(b.version, a.version, true));
39
+ delete globalThis.self;
40
+ return worktimes;
41
+ }
42
+
43
+ const worktimes = getWorktimes();
44
+ module.exports.worktimes = worktimes;
@@ -268,7 +268,11 @@ self.wrapScriptLoading({ scriptName: 'bootstrap', finalScript: true }, function
268
268
  return;
269
269
  // Avoid sending duplicate console message data over the network.
270
270
  delete lastConsoleLog.message;
271
- postMessage({ request: 'console', payload: lastConsoleLog });
272
- lastConsoleLog = null;
271
+ try
272
+ {
273
+ postMessage({ request: 'console', payload: lastConsoleLog });
274
+ lastConsoleLog = null;
275
+ }
276
+ catch (e){}
273
277
  };
274
278
  });
@@ -11,282 +11,50 @@
11
11
 
12
12
  self.wrapScriptLoading({ scriptName: 'bravojs-env' }, function bravojsEvn$$fn(protectedStorage, _ring2PostMessage, wrapPostMessage)
13
13
  {
14
- // This file starts at ring 2, but transitions to ring 3 partway through it.
15
14
  const ring2PostMessage = self.postMessage;
16
- let ring3PostMessage;
17
-
18
15
  bravojs.ww = {}
19
16
  bravojs.ww.allDeps = []
20
17
  bravojs.ww.provideCallbacks = {}
21
18
 
22
19
  //Listens for postMessage from the sandbox
23
- addEventListener('message', async (event) => {
20
+ addEventListener('message', async function bravojsEnv$$sandboxPostMessageHandler(event) {
24
21
  let message = event
25
22
  let indirectEval = eval // eslint-disable-line
26
- switch (message.request) {
23
+ switch (message.request)
24
+ {
27
25
  case 'moduleGroup': /* Outside environment is sending us a module group */
28
26
  module.declare = bravojs.ww.groupedModuleDeclare
29
27
  let packages = Object.keys(message.data)
30
28
 
31
- for (let i = 0; i < packages.length; i++) {
29
+ for (let i = 0; i < packages.length; i++)
30
+ {
32
31
  let fileNames = Object.keys(message.data[packages[i]])
33
- for (let j = 0; j < fileNames.length; j++) {
32
+ for (let j = 0; j < fileNames.length; j++)
33
+ {
34
34
  bravojs.ww.moduleId = packages[i] + '/' + fileNames[j]
35
- try {
36
- indirectEval(message.data[packages[i]][fileNames[j]], fileNames[j])
37
- } catch (error) {
38
- throw error
39
- }
35
+ indirectEval(message.data[packages[i]][fileNames[j]], fileNames[j])
40
36
  }
41
37
  }
42
38
 
43
39
  delete module.declare
44
40
 
45
- if (bravojs.ww.provideCallbacks.hasOwnProperty(message.id)) {
41
+ if (bravojs.ww.provideCallbacks.hasOwnProperty(message.id))
42
+ {
46
43
  bravojs.ww.provideCallbacks[message.id].callback()
47
44
  delete bravojs.ww.provideCallbacks[message.id]
48
45
  }
49
46
  break
50
47
  case 'moduleGroupError': /* Outside environment is sending us a module group error report */
51
- if (bravojs.ww.provideCallbacks.hasOwnProperty(message.id) && bravojs.ww.provideCallbacks[message.id].onerror) {
52
- bravojs.ww.provideCallbacks[message.id].onerror()
53
- } else {
54
- console.error('moduleGroupError ', message.stack)
55
- }
56
- break
57
-
58
- /* Sandbox assigned a specific job by supervisor */
59
- case 'assign': {
60
- let reportError = function bravojsEnv$$sandboxAssignment$reportError(e) {
61
- var error = Object.assign({}, e);
62
- Object.getOwnPropertyNames(e).forEach((prop) => error[prop] = e[prop]);
63
- if (error.stack)
64
- error = error.stack.replace(/data:application\/javascript.*?:/g, 'eval:');
65
-
66
- ring2PostMessage({request: 'reject', error});
67
- }
68
-
69
- try {
70
- if (typeof module.main !== 'undefined')
71
- throw new Error('Main module was provided before job assignment');
72
-
73
- protectedStorage.sandboxConfig = message.sandboxConfig;
74
- Object.assign(self.work.job.public, message.job.public); /* override locale-specific defaults if specified */
75
- // Load bravojs' module.main with the work function
76
- module.declare(message.job.dependencies, async function mainModule(require, exports, module) {
77
- try {
78
- if (exports.hasOwnProperty('job'))
79
- throw new Error("Tried to assign sandbox when it was already assigned"); /* Should be impossible - might happen if throw during assign? */
80
- exports.job = false; /* placeholder own property */
81
-
82
- message.job.requirePath.map(p => require.paths.push(p));
83
- message.job.modulePath.map(p => module.paths.push(p));
84
- exports.arguments = message.job.arguments;
85
- exports.worktime = message.job.worktime;
86
-
87
- switch (message.job.worktime.name)
88
- {
89
- case 'map-basic':
90
- if (message.job.useStrict)
91
- exports.job = indirectEval(`"use strict"; (${message.job.workFunction})`);
92
- else
93
- exports.job = indirectEval(`(${message.job.workFunction})`);
94
- break;
95
- case 'pyodide':
96
- exports.job = await generatePyodideFunction(message.job);
97
- break;
98
- default:
99
- throw new Error(`Unsupported worktime: ${message.job.worktime.name}`);
100
- }
101
- } catch(e) {
102
- reportError(e);
103
- return;
104
- }
105
-
106
- ring2PostMessage({
107
- request: 'assigned',
108
- jobId: message.job.id,
109
- });
110
-
111
- // Now that the evaluator is assigned, wrap post message for ring 3
112
- wrapPostMessage();
113
- ring3PostMessage = self.postMessage;
114
- }); /* end of main module */
115
- } catch (error) {
116
- reportError(error);
117
- }
118
- break /* end of assign */
119
- }
120
- /* Supervisor has asked us to execute the work function. message.data is input datum. */
121
- case 'main':
122
- {
123
- try
124
- {
125
- await runWorkFunction(message.data);
126
- }
127
- catch (error)
128
- {
129
- ring3PostMessage({ request: 'sandboxError', error });
130
- }
48
+ if (bravojs.ww.provideCallbacks.hasOwnProperty(message.id) && bravojs.ww.provideCallbacks[message.id].onerror)
49
+ bravojs.ww.provideCallbacks[message.id].onerror();
50
+ else
51
+ console.error('moduleGroupError ', message.stack);
131
52
  break;
132
- }
133
53
  default:
134
54
  break;
135
55
  }
136
56
  })
137
57
 
138
- /**
139
- * Factory function which generates a "map-basic"-like workFunction
140
- * out of a Pyodide Worktime job (Python code, files, env variables).
141
- *
142
- * It takes any "images" passed in the workFunction "arguments" and
143
- * writes them to the in memory filesystem provided by Emscripten.
144
- * It adds any environment variables specified in the workFunction
145
- * "arguments" to the pseudo-"process" for use.
146
- * It globally imports a dcp module with function "set_slice_handler"
147
- * which takes a python function as input. The python function passed
148
- * to that slice handler is invoked by the function which this
149
- * factory function returns.
150
- *
151
- * @param {Object} job The job data associated with the message
152
- * @returns {Function} function pyodideWorkFn(slice) -> result
153
- */
154
- async function generatePyodideFunction(job)
155
- {
156
- var pythonSliceHandler;
157
-
158
- const pyodide = await pyodideInit();
159
- const sys = pyodide.pyimport('sys');
160
-
161
- const findImports = pyodide.runPython('import pyodide; pyodide.code.find_imports');
162
- const findPythonModuleLoader = pyodide.runPython('import importlib; importlib.util.find_spec');
163
-
164
- const parsedArguments = parsePyodideArguments(job.arguments);
165
-
166
- // write images to file and set environment variables
167
- const prepPyodide = pyodide.runPython(`
168
- import tarfile, io
169
- import os, sys
170
-
171
- def prepPyodide(args):
172
- for image in args['images']:
173
- image = bytes(image)
174
- imageFile = io.BytesIO(image)
175
- tar = tarfile.open(mode='r', fileobj=imageFile)
176
-
177
- # Don't overwrite directories which corrupts Pyodide's in memory filesystem
178
- def safe_extract(tar, path="/"):
179
- for member in tar.getmembers():
180
- if member.isdir():
181
- dir_path = os.path.join(path, member.name)
182
- if not os.path.exists(dir_path):
183
- os.makedirs(dir_path)
184
- else:
185
- tar.extract(member, path)
186
- safe_extract(tar)
187
-
188
- for item, value in args['environmentVariables'].items():
189
- os.environ[item] = value
190
-
191
- sys.argv.extend(args['sysArgv'])
192
-
193
- return
194
-
195
- prepPyodide`);
196
-
197
- prepPyodide(pyodide.toPy(parsedArguments));
198
-
199
- // register the dcp Python module
200
- if (!sys.modules.get('dcp'))
201
- {
202
- const create_proxy = pyodide.runPython('import pyodide;pyodide.ffi.create_proxy');
203
-
204
- pyodide.registerJsModule('dcp', {
205
- set_slice_handler: function pyodide$$dcp$$setSliceHandler(func) {
206
- pythonSliceHandler = create_proxy(func);
207
- },
208
- progress,
209
- });
210
- }
211
- pyodide.runPython( 'import dcp' );
212
-
213
- // attempt to import packages from the package manager (if they're not already loaded)
214
- const workFunctionPythonImports = findImports(job.workFunction).toJs();
215
- const packageManagerImports = workFunctionPythonImports.filter(x=>!findPythonModuleLoader(x));
216
- if (packageManagerImports.length > 0)
217
- {
218
- await fetchAndInitPyodidePackages(packageManagerImports);
219
- await pyodide.loadPackage(packageManagerImports);
220
- }
221
-
222
- return workFunctionWrapper;
223
-
224
- /**
225
- * Evaluates the Python WorkFunction string and then executes the slice
226
- * handler Python function. If no call to `dcp.set_slice_handler` is passed
227
- * or a non function is passed to it.
228
- * This function specifically only takes one parameter since Pyodide Slice
229
- * Handlers only accept one parameter.
230
- */
231
- async function workFunctionWrapper(datum)
232
- {
233
- const pyodide = await pyodideInit(); // returns the same promise when called multiple times
234
-
235
- // load and execute the Python Workfunction, this populates the pythonSliceHandler variable
236
- await pyodide.runPython(job.workFunction);
237
-
238
- // failure to specify a slice handler is considered an error
239
- if (!pythonSliceHandler)
240
- throw new Error('ENOSLICEHANDLER: Must specify the slice handler using `dcp.set_slice_handler(fn)`');
241
-
242
- // setting the slice handler to a non function or lambda is not supported
243
- else if (typeof pythonSliceHandler !== 'function')
244
- throw new Error('ENOSLICEHANDLER: Slice Handler must be a function');
245
-
246
- const sliceHandlerResult = await pythonSliceHandler(pyodide.toPy(datum));
247
-
248
- // if it is a PyProxy, convert its value to JavaScript
249
- if (sliceHandlerResult?.toJs)
250
- return sliceHandlerResult.toJs();
251
-
252
- return sliceHandlerResult;
253
- }
254
-
255
- /*
256
- * Refer to the "The Pyodide Worktime"."Work Function (JS)"."Arguments"."Commands"
257
- * part of the DCP Worktimes spec.
258
- */
259
- function parsePyodideArguments(args)
260
- {
261
- var index = 1;
262
- const numArgs = args[0];
263
- const images = [];
264
- const environmentVariables = {};
265
- const sysArgv = args.slice(numArgs);
266
-
267
- while (index < numArgs)
268
- {
269
- switch (args[index])
270
- {
271
- case 'gzImage':
272
- const image = args[index+1];
273
- images.push(image);
274
- index+=2;
275
- break;
276
- case 'env':
277
- const env = args[index+1].split(/=(.*)/s);
278
- index+=2;
279
- environmentVariables[env[0]] = env[1];
280
- break;
281
- default:
282
- throw new Error(`Invalid argument ${args[index]}`);
283
- }
284
- }
285
-
286
- return { sysArgv, images, environmentVariables };
287
- }
288
- }
289
-
290
58
  /** A module.declare suitable for running when processing modules arriving as part
291
59
  * of a module group or other in-memory cache.
292
60
  */
@@ -296,7 +64,8 @@ prepPyodide`);
296
64
 
297
65
  if (bravojs.debug && bravojs.debug.match(/\bmoduleCache\b/)) { console.log('Loaded ' + dependencies + ' from group') }
298
66
 
299
- if (typeof moduleFactory === 'undefined') {
67
+ if (typeof moduleFactory === 'undefined')
68
+ {
300
69
  moduleFactory = dependencies
301
70
  dependencies = []
302
71
  }
@@ -306,9 +75,8 @@ prepPyodide`);
306
75
  dependencies: dependencies
307
76
  }
308
77
 
309
- for (i = 0; i < dependencies.length; i++) {
78
+ for (i = 0; i < dependencies.length; i++)
310
79
  bravojs.ww.allDeps.push(bravojs.makeModuleId(moduleBase, dependencies[i]))
311
- }
312
80
  }
313
81
 
314
82
  /** A module.provide suitable for a web worker, which requests modules via message passing.
@@ -335,137 +103,4 @@ prepPyodide`);
335
103
  id,
336
104
  });
337
105
  };
338
-
339
- /* Report metrics to sandbox/supervisor */
340
- function reportTimes (metrics)
341
- {
342
- const { total, webGL, webGPU, CPU } = metrics;
343
- ring3PostMessage({ request: 'measurement', total, webGL, webGPU, CPU });
344
- }
345
-
346
- /* Report an error from the work function to the supervisor */
347
- function reportError (error, metrics)
348
- {
349
- const err = new Error('initial state');
350
-
351
- for (let prop of [ 'message', 'name', 'code', 'stack', 'lineNumber', 'columnNumber' ])
352
- {
353
- try
354
- {
355
- if (typeof error[prop] !== 'undefined')
356
- err[prop] = error[prop];
357
- }
358
- catch(e){};
359
- }
360
-
361
- reportTimes(metrics); // Report metrics for both 'workReject' and 'workError'.
362
- ring3PostMessage({ request: 'workError', error: err });
363
- }
364
-
365
- /**
366
- * Report a result from work function and metrics to the supervisor.
367
- * @param result the value that the work function returned promise resolved to
368
- */
369
- function reportResult (result, metrics)
370
- {
371
- try
372
- {
373
- reportTimes(metrics);
374
- ring3PostMessage({ request: 'complete', result });
375
- }
376
- catch (error)
377
- {
378
- ring3PostMessage({ request: 'sandboxError', error });
379
- }
380
- }
381
-
382
- /**
383
- * Actual mechanics for running a work function. ** This function will never reject **
384
- *
385
- * @param successCallback callback to invoke when the work function has finished running;
386
- * it receives as its argument the resolved promise returned from
387
- * the work function
388
- * @param errorCallback callback to invoke when the work function rejects. It receives
389
- * as its argument the error that it rejected with.
390
- * @returns unused promise
391
- */
392
- async function runWorkFunction_inner(datum, wallDuration, successCallback, errorCallback)
393
- {
394
- /** @typedef {import("./timer-classes.js").TimeInterval} TimeInterval */
395
- var rejection = false;
396
- var result;
397
- let metrics;
398
- protectedStorage.emitConsoleMessages = true;
399
- protectedStorage.flushConsoleBuffer();
400
- try
401
- {
402
- /* module.main.job is the work function; left by assign message */
403
- result = await module.main.job.apply(null, [datum].concat(module.main.arguments));
404
- }
405
- catch (error)
406
- {
407
- rejection = error;
408
- }
409
-
410
- try {
411
- // reset the device states and flush all pending tasks
412
- protectedStorage.lockTimers(); // lock timers so no new timeouts will be run.
413
- if (protectedStorage.webGPU)
414
- protectedStorage.webGPU.lock();
415
-
416
- // Let microtask queue finish before getting metrics. With all event-loop possibilities locked,
417
- // only the microtask could trigger new code, so waiting for a setTimeout guarantees everything's done
418
- await new Promise((r) => protectedStorage.realSetTimeout.call(globalThis, r, 1));
419
-
420
- // flush any pending console events, especially in the case of a repeating message that hasn't been emitted yet
421
- // then, disable emission of any more console messages
422
- try { protectedStorage.dispatchSameConsoleMessage(); } catch(e) {};
423
- protectedStorage.emitConsoleMessages = false;
424
-
425
- metrics = await protectedStorage.bigBrother.globalTrackers.getMetrics();
426
-
427
- await protectedStorage.bigBrother.globalTrackers.reset();
428
- } catch (e) {
429
- ring3PostMessage({ request: 'sandboxError', error: e });
430
- } finally {
431
- // due to the nature of the micro task queue, await, our `reset()` cancels all the things that could cause new
432
- // tasks, and we wait for all pending task to finish in `reset()`, we are guaranteed to have an empty task queue
433
- // now. Hence it's ok to stop the wall clock measurement now
434
- wallDuration.stop();
435
-
436
- // safety: wallDuration is always stopped, `length` will not throw
437
- metrics = { ...metrics, total: wallDuration.length };
438
- }
439
-
440
- if (rejection)
441
- errorCallback(rejection, metrics);
442
- else
443
- successCallback(result, metrics);
444
-
445
- /* CPU time measurement ends when this function's return value is resolved or rejected */
446
- }
447
-
448
- /**
449
- * Run the work function, returning a promise that resolves once the function has finished
450
- * executing.
451
- *
452
- * @param {datam} an element of the input set
453
- */
454
- async function runWorkFunction(datum)
455
- {
456
- // reset the time used for feature detection
457
- protectedStorage.bigBrother.globalTrackers.resetRecordedTime();
458
- const wallDuration = new protectedStorage.TimeInterval();
459
- protectedStorage.bigBrother.globalTrackers.wallDuration = wallDuration;
460
-
461
- if (protectedStorage.webGPU)
462
- protectedStorage.webGPU.unlock();
463
- await protectedStorage.unlockTimers();
464
-
465
- /* Use setTimeout trampoline to
466
- * 1. shorten stack
467
- * 2. initialize the event loop measurement code
468
- */
469
- protectedStorage.setTimeout(() => runWorkFunction_inner(datum, wallDuration, (result, metrics) => reportResult(result, metrics), (rejection, metrics) => reportError(rejection, metrics)));
470
- }
471
106
  }); /* end of fn */
@@ -90,7 +90,7 @@ self.wrapScriptLoading({ scriptName: 'calculate-capabilities' }, function calcul
90
90
  addEventListener('message', async (event) => {
91
91
  try {
92
92
  if (event.request === 'describe') {
93
- const worktimes = globalThis.worktimes;
93
+ const worktimes = protectedStorage.worktimes.getWorktimeList();
94
94
  const capabilities = await getCapabilities();
95
95
  ring2PostMessage({
96
96
  capabilities,
@@ -0,0 +1,53 @@
1
+ /**
2
+ * This file registers the map-basic worktime for DCP. The map-basic worktime is
3
+ * the default worktime used with compute.for, compute.do, etc...
4
+ *
5
+ * Copyright (c) 2018-2024, Distributive, Ltd. All Rights Reserved.
6
+ * @author Severn Lortie <severn@distributive.network>
7
+ */
8
+ // @ts-nocheck
9
+ self.wrapScriptLoading({ scriptName: 'map-basic-worktime' }, function mapBasicWorktime$$fn(protectedStorage, ring1PostMessage, wrapPostMessage) {
10
+ let workFunction;
11
+ let workFunctionArguments;
12
+ /**
13
+ * Registers the worktime callbacks that allow the worktime controller (worktimes.js) to setup our environment and run the worktime
14
+ */
15
+ function registerWorktime()
16
+ {
17
+ protectedStorage.worktimes.registerWorktime({
18
+ name: 'map-basic',
19
+ version: '1.0.0',
20
+ initSandbox,
21
+ processSlice,
22
+ });
23
+ }
24
+
25
+ /**
26
+ * Perform setup tasks before processSlice is run
27
+ * @param {object} job The job assigned to this sandbox
28
+ */
29
+ function initSandbox(job)
30
+ {
31
+ workFunctionArguments = job.arguments;
32
+ workFunctionArguments.unshift(false);
33
+
34
+ const indirectEval = eval;
35
+ if (job.useStrict)
36
+ workFunction = indirectEval(`"use strict"; (${job.workFunction})`);
37
+ else
38
+ workFunction = indirectEval(`(${job.workFunction})`);
39
+ }
40
+
41
+ /**
42
+ * The processSlice hook function which runs the work function for input slice data
43
+ * @param {*} data The slice data
44
+ * @returns {*} The slice result
45
+ */
46
+ async function processSlice(data)
47
+ {
48
+ workFunctionArguments[0] = data;
49
+ const result = await workFunction.apply(null, workFunctionArguments);
50
+ return result;
51
+ }
52
+ registerWorktime();
53
+ });