dcp-client 4.3.6 → 4.3.8
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/README.md +18 -0
- package/dist/dcp-client-bundle.js +1 -1
- package/generated/sandbox-definitions.json +1 -1
- package/index.js +6 -0
- package/libexec/sandbox/access-lists.js +60 -39
- package/libexec/sandbox/bravojs-env.js +159 -6
- package/libexec/sandbox/calculate-capabilities.js +2 -0
- package/libexec/sandbox/pyodide-core.js +3 -0
- package/libexec/sandbox/sa-ww-simulation.js +0 -1
- package/libexec/sandbox/worktimes.js +66 -0
- package/libexec/sandbox/wrap-event-listeners.js +49 -16
- package/licenses/pyodide.LICENSE.txt +376 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"browser":["deny-node","kvin/kvin.js","script-load-wrapper","wrap-event-listeners","timer-classes","event-loop-virtualization","unique-timing","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","calculate-capabilities","bootstrap"],"node":["kvin/kvin.js","sa-ww-simulation","script-load-wrapper","wrap-event-listeners","timer-classes","event-loop-virtualization","unique-timing","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","calculate-capabilities","bootstrap"],"native":["deny-node","kvin/kvin.js","sa-ww-simulation","script-load-wrapper","native-event-loop","wrap-event-listeners","timer-classes","event-loop-virtualization","unique-timing","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","calculate-capabilities","bootstrap"],"nodeTesting":["kvin/kvin.js","sa-ww-simulation","script-load-wrapper","wrap-event-listeners","timer-classes","event-loop-virtualization","unique-timing","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","calculate-capabilities","bootstrap","testing.js"],"testing":["deny-node","kvin/kvin.js","sa-ww-simulation","script-load-wrapper","native-event-loop","wrap-event-listeners","timer-classes","event-loop-virtualization","unique-timing","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","calculate-capabilities","bootstrap","testing.js"]}
|
|
1
|
+
{"browser":["deny-node","kvin/kvin.js","script-load-wrapper","wrap-event-listeners","timer-classes","event-loop-virtualization","unique-timing","worktimes","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","pyodide-core","calculate-capabilities","bootstrap"],"node":["kvin/kvin.js","sa-ww-simulation","script-load-wrapper","wrap-event-listeners","timer-classes","event-loop-virtualization","unique-timing","worktimes","access-lists","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","wrap-event-listeners","timer-classes","event-loop-virtualization","unique-timing","worktimes","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","pyodide-core","calculate-capabilities","bootstrap"],"nodeTesting":["kvin/kvin.js","sa-ww-simulation","script-load-wrapper","wrap-event-listeners","timer-classes","event-loop-virtualization","unique-timing","worktimes","access-lists","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","wrap-event-listeners","timer-classes","event-loop-virtualization","unique-timing","worktimes","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","pyodide-core","calculate-capabilities","bootstrap","testing.js"]}
|
package/index.js
CHANGED
|
@@ -373,11 +373,17 @@ function magicView(node, seen)
|
|
|
373
373
|
*
|
|
374
374
|
* Returns false is the file simply does not exist.
|
|
375
375
|
*
|
|
376
|
+
* Setting `DCP_CLIENT_ALLOW_INSECURE_CONFIGURATION` to a non-empty value disables
|
|
377
|
+
* the security check.
|
|
378
|
+
*
|
|
376
379
|
* @param {string} fullPath the full path to the file to check
|
|
377
380
|
* @param {object} statBuf [optional] existing stat buf for the file
|
|
378
381
|
*/
|
|
379
382
|
function checkConfigFileSafePerms(fullPath, statBuf)
|
|
380
383
|
{
|
|
384
|
+
if (process.env.DCP_CLIENT_ALLOW_INSECURE_CONFIGURATION)
|
|
385
|
+
return true;
|
|
386
|
+
|
|
381
387
|
const fun = checkConfigFileSafePerms;
|
|
382
388
|
|
|
383
389
|
if (!fs.existsSync(fullPath))
|
|
@@ -12,35 +12,17 @@ self.wrapScriptLoading({ scriptName: 'access-lists', ringTransition: true }, fun
|
|
|
12
12
|
const ring1PostMessage = self.postMessage;
|
|
13
13
|
const global = typeof globalThis === 'undefined' ? self : globalThis;
|
|
14
14
|
|
|
15
|
-
// aggregated from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects#Reflection
|
|
16
15
|
const allowList = new Set([
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// properties guarnteed by polyfills
|
|
20
|
-
'globalThis',
|
|
21
|
-
'location',
|
|
22
|
-
'performance',
|
|
23
|
-
'importScripts',
|
|
24
|
-
'WorkerGlobalScope',
|
|
25
|
-
'btoa',
|
|
26
|
-
'atob',
|
|
27
|
-
'Blob',
|
|
28
|
-
|
|
29
|
-
// General allowed symbols
|
|
30
|
-
'addEventListener',
|
|
31
|
-
'applyAccesslist',
|
|
16
|
+
// global objects, aggregated from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects#Reflection
|
|
17
|
+
'AggregateError',
|
|
32
18
|
'Array',
|
|
33
19
|
'ArrayBuffer',
|
|
34
|
-
'AsyncFunction',
|
|
35
20
|
'Atomics',
|
|
36
21
|
'BigInt',
|
|
37
22
|
'BigInt64Array',
|
|
38
23
|
'BigUint64Array',
|
|
39
24
|
'Boolean',
|
|
40
|
-
|
|
41
|
-
'clearInterval',
|
|
42
|
-
'clearTimeout',
|
|
43
|
-
'console',
|
|
25
|
+
|
|
44
26
|
'constructor',
|
|
45
27
|
'DataView',
|
|
46
28
|
'Date',
|
|
@@ -52,12 +34,10 @@ self.wrapScriptLoading({ scriptName: 'access-lists', ringTransition: true }, fun
|
|
|
52
34
|
'escape',
|
|
53
35
|
'eval',
|
|
54
36
|
'EvalError',
|
|
55
|
-
'File',
|
|
56
|
-
'FileReader',
|
|
57
37
|
'Float32Array',
|
|
58
38
|
'Float64Array',
|
|
59
39
|
'Function',
|
|
60
|
-
'
|
|
40
|
+
'globalThis',
|
|
61
41
|
'Infinity',
|
|
62
42
|
'Int16Array',
|
|
63
43
|
'Int32Array',
|
|
@@ -69,7 +49,6 @@ self.wrapScriptLoading({ scriptName: 'access-lists', ringTransition: true }, fun
|
|
|
69
49
|
'Math',
|
|
70
50
|
'module',
|
|
71
51
|
'NaN',
|
|
72
|
-
'navigator',
|
|
73
52
|
'null',
|
|
74
53
|
'Number',
|
|
75
54
|
'Object',
|
|
@@ -82,21 +61,14 @@ self.wrapScriptLoading({ scriptName: 'access-lists', ringTransition: true }, fun
|
|
|
82
61
|
'Promise',
|
|
83
62
|
'propertyIsEnumerable',
|
|
84
63
|
'Proxy',
|
|
85
|
-
'pt0',
|
|
86
64
|
'RangeError',
|
|
87
65
|
'ReferenceError',
|
|
88
66
|
'Reflect',
|
|
89
67
|
'RegExp',
|
|
90
|
-
'removeEventListener',
|
|
91
|
-
'requestAnimationFrame',
|
|
92
68
|
'require',
|
|
93
69
|
'Response',
|
|
94
|
-
'self',
|
|
95
70
|
'Set',
|
|
96
|
-
'
|
|
97
|
-
'setTimeout',
|
|
98
|
-
'setImmediate',
|
|
99
|
-
'sleep',
|
|
71
|
+
'SharedArrayBuffer',
|
|
100
72
|
'String',
|
|
101
73
|
'Symbol',
|
|
102
74
|
'SyntaxError',
|
|
@@ -106,7 +78,6 @@ self.wrapScriptLoading({ scriptName: 'access-lists', ringTransition: true }, fun
|
|
|
106
78
|
'toString',
|
|
107
79
|
'TypeError',
|
|
108
80
|
'URIError',
|
|
109
|
-
'URL',
|
|
110
81
|
'Uint16Array',
|
|
111
82
|
'Uint32Array',
|
|
112
83
|
'Uint8Array',
|
|
@@ -116,10 +87,44 @@ self.wrapScriptLoading({ scriptName: 'access-lists', ringTransition: true }, fun
|
|
|
116
87
|
'valueOf',
|
|
117
88
|
'WeakMap',
|
|
118
89
|
'WeakSet',
|
|
90
|
+
'WeakRef',
|
|
91
|
+
'__proto__',
|
|
92
|
+
|
|
93
|
+
// WorkerGlobalScope symbols, aggregated from https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope
|
|
94
|
+
// 'caches',
|
|
95
|
+
//'crossOriginIsolated',
|
|
96
|
+
'crypto',
|
|
97
|
+
//'fonts',
|
|
98
|
+
// 'indexedDB',
|
|
99
|
+
'isSecureContext',
|
|
100
|
+
'location',
|
|
101
|
+
'navigator',
|
|
102
|
+
//'origin',
|
|
103
|
+
'performance',
|
|
104
|
+
// 'scheduler',
|
|
105
|
+
'self',
|
|
106
|
+
'console',
|
|
107
|
+
'atob',
|
|
108
|
+
'btoa',
|
|
109
|
+
'clearInterval',
|
|
110
|
+
'clearTimeout',
|
|
111
|
+
// 'fetch',
|
|
112
|
+
// 'importScripts',
|
|
113
|
+
'queueMicrotask',
|
|
114
|
+
'setInterval',
|
|
115
|
+
'setTimeout',
|
|
116
|
+
'structuredClone',
|
|
117
|
+
'reportError',
|
|
118
|
+
'WorkerGlobalScope',
|
|
119
|
+
|
|
120
|
+
// WebAssembly symbols
|
|
119
121
|
'WebAssembly',
|
|
122
|
+
|
|
123
|
+
// WebGL symbols
|
|
120
124
|
'WebGL2RenderingContext',
|
|
121
125
|
'WebGLTexture',
|
|
122
|
-
|
|
126
|
+
|
|
127
|
+
// WebGPU symbols
|
|
123
128
|
'WebGPUWindow',
|
|
124
129
|
'GPU',
|
|
125
130
|
'GPUAdapter',
|
|
@@ -161,9 +166,15 @@ self.wrapScriptLoading({ scriptName: 'access-lists', ringTransition: true }, fun
|
|
|
161
166
|
'GPUTextureView',
|
|
162
167
|
'GPUUncapturedErrorEvent',
|
|
163
168
|
'GPUValidationError',
|
|
164
|
-
|
|
169
|
+
|
|
170
|
+
// DCP symbols / chosen web API additions
|
|
165
171
|
'progress',
|
|
166
172
|
'work',
|
|
173
|
+
'bravojs',
|
|
174
|
+
'setImmediate',
|
|
175
|
+
'Blob',
|
|
176
|
+
'addEventListener',
|
|
177
|
+
'removeEventListener',
|
|
167
178
|
]);
|
|
168
179
|
|
|
169
180
|
// Origin time for performance polyfill
|
|
@@ -178,15 +189,15 @@ self.wrapScriptLoading({ scriptName: 'access-lists', ringTransition: true }, fun
|
|
|
178
189
|
// Assumption that if performance exists, performance.now must exist
|
|
179
190
|
performance: typeof performance !== 'undefined' ? performance : {
|
|
180
191
|
now: ()=>{
|
|
181
|
-
res = new Date().getTime() - pt0;
|
|
192
|
+
const res = new Date().getTime() - pt0;
|
|
182
193
|
return res;
|
|
183
194
|
}
|
|
184
195
|
},
|
|
185
196
|
importScripts: function () {
|
|
186
197
|
throw new Error('importScripts is not supported on DCP');
|
|
187
198
|
},
|
|
188
|
-
WorkerGlobalScope: typeof globalThis === 'undefined' ? self : globalThis,
|
|
189
199
|
globalThis: typeof globalThis === 'undefined' ? self : globalThis,
|
|
200
|
+
WorkerGlobalScope: typeof globalThis === 'undefined' ? self : globalThis,
|
|
190
201
|
// For browsers/SA-workers that don't support btoa/atob, modified from https://github.com/MaxArt2501/base64-js/blob/master/base64.js
|
|
191
202
|
btoa: function (string) {
|
|
192
203
|
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
|
@@ -673,7 +684,7 @@ self.wrapScriptLoading({ scriptName: 'access-lists', ringTransition: true }, fun
|
|
|
673
684
|
function applyAccessLists(obj, allowList, blockList = {}) {
|
|
674
685
|
if (!obj) { return; }
|
|
675
686
|
Object.getOwnPropertyNames(obj).forEach(function (prop) {
|
|
676
|
-
if (Object.getOwnPropertyDescriptor(obj, prop)
|
|
687
|
+
if (Object.getOwnPropertyDescriptor(obj, prop)?.configurable) {
|
|
677
688
|
if (!allowList.has(prop)) {
|
|
678
689
|
let isSet = false;
|
|
679
690
|
let propValue;
|
|
@@ -809,6 +820,12 @@ self.wrapScriptLoading({ scriptName: 'access-lists', ringTransition: true }, fun
|
|
|
809
820
|
};
|
|
810
821
|
}
|
|
811
822
|
|
|
823
|
+
function allowWorktimeSymbols(symbols)
|
|
824
|
+
{
|
|
825
|
+
for (let symbol of symbols)
|
|
826
|
+
allowList.add(symbol);
|
|
827
|
+
}
|
|
828
|
+
|
|
812
829
|
addEventListener('message', async (event) => {
|
|
813
830
|
try {
|
|
814
831
|
if (event.request === 'applyRequirements') {
|
|
@@ -819,6 +836,10 @@ self.wrapScriptLoading({ scriptName: 'access-lists', ringTransition: true }, fun
|
|
|
819
836
|
blockList.OffscreenCanvas = !requirements.environment.offscreenCanvas;
|
|
820
837
|
blockList.WebGPUWindow = !requirements.environment.webgpu;
|
|
821
838
|
blockList.GPU = !requirements.environment.webgpu;
|
|
839
|
+
|
|
840
|
+
if (event.worktime && protectedStorage.worktimeGlobals[event.worktime])
|
|
841
|
+
allowWorktimeSymbols(protectedStorage.worktimeGlobals[event.worktime]);
|
|
842
|
+
|
|
822
843
|
applyAllAccessLists();
|
|
823
844
|
|
|
824
845
|
ring1PostMessage({ request: 'applyRequirementsDone' });
|
|
@@ -74,7 +74,7 @@ self.wrapScriptLoading({ scriptName: 'bravojs-env', ringTransition: true }, func
|
|
|
74
74
|
protectedStorage.sandboxConfig = message.sandboxConfig;
|
|
75
75
|
Object.assign(self.work.job.public, message.job.public); /* override locale-specific defaults if specified */
|
|
76
76
|
// Load bravojs' module.main with the work function
|
|
77
|
-
module.declare(message.job.dependencies || (message.job.requireModules /* deprecated */), function mainModule(require, exports, module) {
|
|
77
|
+
module.declare(message.job.dependencies || (message.job.requireModules /* deprecated */), async function mainModule(require, exports, module) {
|
|
78
78
|
try {
|
|
79
79
|
if (exports.hasOwnProperty('job'))
|
|
80
80
|
throw new Error("Tried to assign sandbox when it was already assigned"); /* Should be impossible - might happen if throw during assign? */
|
|
@@ -83,11 +83,22 @@ self.wrapScriptLoading({ scriptName: 'bravojs-env', ringTransition: true }, func
|
|
|
83
83
|
message.job.requirePath.map(p => require.paths.push(p));
|
|
84
84
|
message.job.modulePath.map(p => module.paths.push(p));
|
|
85
85
|
exports.arguments = message.job.arguments;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
exports.worktime = message.job.worktime;
|
|
87
|
+
|
|
88
|
+
switch (message.job.worktime.name)
|
|
89
|
+
{
|
|
90
|
+
case 'map-basic':
|
|
91
|
+
if (message.job.useStrict)
|
|
92
|
+
exports.job = indirectEval(`"use strict"; (${message.job.workFunction})`);
|
|
93
|
+
else
|
|
94
|
+
exports.job = indirectEval(`(${message.job.workFunction})`);
|
|
95
|
+
break;
|
|
96
|
+
case 'pyodide':
|
|
97
|
+
exports.job = await generatePyodideFunction(message.job);
|
|
98
|
+
break;
|
|
99
|
+
default:
|
|
100
|
+
throw new Error(`Unsupported worktime: ${message.job.worktime.name}`);
|
|
101
|
+
}
|
|
91
102
|
} catch(e) {
|
|
92
103
|
reportError(e);
|
|
93
104
|
return;
|
|
@@ -125,6 +136,148 @@ self.wrapScriptLoading({ scriptName: 'bravojs-env', ringTransition: true }, func
|
|
|
125
136
|
}
|
|
126
137
|
})
|
|
127
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Factory function which generates a "map-basic"-like workFunction
|
|
141
|
+
* out of a Pyodide Worktime job (Python code, files, env variables).
|
|
142
|
+
*
|
|
143
|
+
* It takes any "images" passed in the workFunction "arguments" and
|
|
144
|
+
* writes them to the in memory filesystem provided by Emscripten.
|
|
145
|
+
* It adds any environment variables specified in the workFunction
|
|
146
|
+
* "arguments" to the pseudo-"process" for use.
|
|
147
|
+
* It globally imports a dcp module with function "set_slice_handler"
|
|
148
|
+
* which takes a python function as input. The python function passed
|
|
149
|
+
* to that slice handler is invoked by the function which this
|
|
150
|
+
* factory function returns.
|
|
151
|
+
*
|
|
152
|
+
* @param {Object} job The job data associated with the message
|
|
153
|
+
* @returns {Function} function pyodideWorkFn(slice) -> result
|
|
154
|
+
*/
|
|
155
|
+
async function generatePyodideFunction(job)
|
|
156
|
+
{
|
|
157
|
+
var pythonSliceHandler;
|
|
158
|
+
|
|
159
|
+
const pyodide = await pyodideInit();
|
|
160
|
+
const sys = pyodide.pyimport('sys');
|
|
161
|
+
|
|
162
|
+
const findImports = pyodide.runPython('import pyodide; pyodide.code.find_imports');
|
|
163
|
+
const findPythonModuleLoader = pyodide.runPython('import importlib; importlib.find_loader');
|
|
164
|
+
|
|
165
|
+
const parsedArguments = parsePyodideArguments(job.arguments);
|
|
166
|
+
|
|
167
|
+
// write images to file and set environment variables
|
|
168
|
+
const prepPyodide = pyodide.runPython(`
|
|
169
|
+
import tarfile, io
|
|
170
|
+
import os, sys
|
|
171
|
+
|
|
172
|
+
def prepPyodide(args):
|
|
173
|
+
for image in args['images']:
|
|
174
|
+
image = bytes(image)
|
|
175
|
+
imageFile = io.BytesIO(image)
|
|
176
|
+
tar = tarfile.open(mode='r', fileobj=imageFile)
|
|
177
|
+
tar.extractall()
|
|
178
|
+
|
|
179
|
+
for item, value in args['environmentVariables'].items():
|
|
180
|
+
os.environ[item] = value
|
|
181
|
+
|
|
182
|
+
sys.argv.extend(args['sysArgv'])
|
|
183
|
+
|
|
184
|
+
return
|
|
185
|
+
|
|
186
|
+
prepPyodide`);
|
|
187
|
+
|
|
188
|
+
prepPyodide(pyodide.toPy(parsedArguments));
|
|
189
|
+
|
|
190
|
+
// register the dcp Python module
|
|
191
|
+
if (!sys.modules.get('dcp'))
|
|
192
|
+
{
|
|
193
|
+
const create_proxy = pyodide.runPython('import pyodide;pyodide.ffi.create_proxy');
|
|
194
|
+
|
|
195
|
+
pyodide.registerJsModule('dcp', {
|
|
196
|
+
set_slice_handler: function pyodide$$dcp$$setSliceHandler(func) {
|
|
197
|
+
pythonSliceHandler = create_proxy(func);
|
|
198
|
+
},
|
|
199
|
+
progress,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
pyodide.runPython( 'import dcp' );
|
|
203
|
+
|
|
204
|
+
// attempt to import packages from the package manager (if they're not already loaded)
|
|
205
|
+
const workFunctionPythonImports = findImports(job.workFunction).toJs();
|
|
206
|
+
const packageManagerImports = workFunctionPythonImports.filter(x=>!findPythonModuleLoader(x));
|
|
207
|
+
if (packageManagerImports.length > 0)
|
|
208
|
+
{
|
|
209
|
+
await fetchAndInitPyodidePackages(packageManagerImports);
|
|
210
|
+
await pyodide.loadPackage(packageManagerImports);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return workFunctionWrapper;
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Evaluates the Python WorkFunction string and then executes the slice
|
|
217
|
+
* handler Python function. If no call to `dcp.set_slice_handler` is passed
|
|
218
|
+
* or a non function is passed to it.
|
|
219
|
+
* This function specifically only takes one parameter since Pyodide Slice
|
|
220
|
+
* Handlers only accept one parameter.
|
|
221
|
+
*/
|
|
222
|
+
async function workFunctionWrapper(datum)
|
|
223
|
+
{
|
|
224
|
+
const pyodide = await pyodideInit(); // returns the same promise when called multiple times
|
|
225
|
+
|
|
226
|
+
// load and execute the Python Workfunction, this populates the pythonSliceHandler variable
|
|
227
|
+
await pyodide.runPython(job.workFunction);
|
|
228
|
+
|
|
229
|
+
// failure to specify a slice handler is considered an error
|
|
230
|
+
if (!pythonSliceHandler)
|
|
231
|
+
throw new Error('ENOSLICEHANDLER: Must specify the slice handler using `dcp.set_slice_handler(fn)`');
|
|
232
|
+
|
|
233
|
+
// setting the slice handler to a non function or lambda is not supported
|
|
234
|
+
else if (typeof pythonSliceHandler !== 'function')
|
|
235
|
+
throw new Error('ENOSLICEHANDLER: Slice Handler must be a function');
|
|
236
|
+
|
|
237
|
+
const sliceHandlerResult = await pythonSliceHandler(datum);
|
|
238
|
+
|
|
239
|
+
// if it is a PyProxy, convert its value to JavaScript
|
|
240
|
+
if (sliceHandlerResult.toJs)
|
|
241
|
+
return sliceHandlerResult.toJs();
|
|
242
|
+
|
|
243
|
+
return sliceHandlerResult;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/*
|
|
247
|
+
* Refer to the "The Pyodide Worktime"."Work Function (JS)"."Arguments"."Commands"
|
|
248
|
+
* part of the DCP Worktimes spec.
|
|
249
|
+
*/
|
|
250
|
+
function parsePyodideArguments(args)
|
|
251
|
+
{
|
|
252
|
+
var index = 1;
|
|
253
|
+
const numArgs = args[0];
|
|
254
|
+
const images = [];
|
|
255
|
+
const environmentVariables = {};
|
|
256
|
+
const sysArgv = args.slice(numArgs);
|
|
257
|
+
|
|
258
|
+
while (index < numArgs)
|
|
259
|
+
{
|
|
260
|
+
switch (args[index])
|
|
261
|
+
{
|
|
262
|
+
case 'gzImage':
|
|
263
|
+
const image = args[index+1];
|
|
264
|
+
images.push(image);
|
|
265
|
+
index+=2;
|
|
266
|
+
break;
|
|
267
|
+
case 'env':
|
|
268
|
+
const env = args[index+1].split(/=(.*)/s);
|
|
269
|
+
index+=2;
|
|
270
|
+
environmentVariables[env[0]] = env[1];
|
|
271
|
+
break;
|
|
272
|
+
default:
|
|
273
|
+
throw new Error(`Invalid argument ${args[index]}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return { sysArgv, images, environmentVariables };
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
128
281
|
/** A module.declare suitable for running when processing modules arriving as part
|
|
129
282
|
* of a module group or other in-memory cache.
|
|
130
283
|
*/
|
|
@@ -133,9 +133,11 @@ self.wrapScriptLoading({ scriptName: 'calculate-capabilities' }, function calcul
|
|
|
133
133
|
addEventListener('message', async (event) => {
|
|
134
134
|
try {
|
|
135
135
|
if (event.request === 'describe') {
|
|
136
|
+
const worktimes = globalThis.worktimes;
|
|
136
137
|
const capabilities = await getCapabilities();
|
|
137
138
|
ring2PostMessage({
|
|
138
139
|
capabilities,
|
|
140
|
+
worktimes,
|
|
139
141
|
request: 'describe',
|
|
140
142
|
});
|
|
141
143
|
}
|