@nodetool-ai/sandbox-runtime 0.0.0-stage → 0.8.9-bootstrap.0
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 +24 -2
- package/dist/.nodetool-build-stamp +1 -0
- package/dist/host-access-gate.d.ts +24 -0
- package/dist/host-access-gate.d.ts.map +1 -0
- package/dist/host-access-gate.js +31 -0
- package/dist/host-access-gate.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +318 -0
- package/dist/index.js.map +1 -0
- package/dist/js-sandbox-worker/engine.d.ts +4 -0
- package/dist/js-sandbox-worker/engine.d.ts.map +1 -0
- package/dist/js-sandbox-worker/engine.js +82 -0
- package/dist/js-sandbox-worker/engine.js.map +1 -0
- package/dist/js-sandbox-worker/host.d.ts +136 -0
- package/dist/js-sandbox-worker/host.d.ts.map +1 -0
- package/dist/js-sandbox-worker/host.js +482 -0
- package/dist/js-sandbox-worker/host.js.map +1 -0
- package/dist/js-sandbox-worker/interpreter.d.ts +276 -0
- package/dist/js-sandbox-worker/interpreter.d.ts.map +1 -0
- package/dist/js-sandbox-worker/interpreter.js +1318 -0
- package/dist/js-sandbox-worker/interpreter.js.map +1 -0
- package/dist/js-sandbox-worker/protocol.d.ts +168 -0
- package/dist/js-sandbox-worker/protocol.d.ts.map +1 -0
- package/dist/js-sandbox-worker/protocol.js +217 -0
- package/dist/js-sandbox-worker/protocol.js.map +1 -0
- package/dist/js-sandbox-worker/worker-entry.d.ts +26 -0
- package/dist/js-sandbox-worker/worker-entry.d.ts.map +1 -0
- package/dist/js-sandbox-worker/worker-entry.js +308 -0
- package/dist/js-sandbox-worker/worker-entry.js.map +1 -0
- package/dist/limits.d.ts +77 -0
- package/dist/limits.d.ts.map +1 -0
- package/dist/limits.js +56 -0
- package/dist/limits.js.map +1 -0
- package/dist/sandbox-bootstrap-modules.d.ts +54 -0
- package/dist/sandbox-bootstrap-modules.d.ts.map +1 -0
- package/dist/sandbox-bootstrap-modules.js +104 -0
- package/dist/sandbox-bootstrap-modules.js.map +1 -0
- package/dist/sandbox-bytes.d.ts +43 -0
- package/dist/sandbox-bytes.d.ts.map +1 -0
- package/dist/sandbox-bytes.js +61 -0
- package/dist/sandbox-bytes.js.map +1 -0
- package/dist/sandbox-canvas-api.d.ts +30 -0
- package/dist/sandbox-canvas-api.d.ts.map +1 -0
- package/dist/sandbox-canvas-api.js +81 -0
- package/dist/sandbox-canvas-api.js.map +1 -0
- package/dist/sandbox-constants.d.ts +5 -0
- package/dist/sandbox-constants.d.ts.map +1 -0
- package/dist/sandbox-constants.js +13 -0
- package/dist/sandbox-constants.js.map +1 -0
- package/dist/sandbox-json-transport.d.ts +107 -0
- package/dist/sandbox-json-transport.d.ts.map +1 -0
- package/dist/sandbox-json-transport.js +324 -0
- package/dist/sandbox-json-transport.js.map +1 -0
- package/dist/timeline-capture.d.ts +21 -0
- package/dist/timeline-capture.d.ts.map +1 -0
- package/dist/timeline-capture.js +564 -0
- package/dist/timeline-capture.js.map +1 -0
- package/dist/utils/type-guards.d.ts +26 -0
- package/dist/utils/type-guards.d.ts.map +1 -0
- package/dist/utils/type-guards.js +44 -0
- package/dist/utils/type-guards.js.map +1 -0
- package/package.json +138 -4
- package/vendor/README.md +17 -0
- package/vendor/quickjs/LICENSE +21 -0
- package/vendor/quickjs/PROVENANCE.json +8 -0
- package/vendor/quickjs/adapter/fetch.d.ts +56 -0
- package/vendor/quickjs/adapter/fetch.js +140 -0
- package/vendor/quickjs/createTimeInterval.d.ts +9 -0
- package/vendor/quickjs/createTimeInterval.js +22 -0
- package/vendor/quickjs/createVirtualFileSystem.d.ts +13 -0
- package/vendor/quickjs/createVirtualFileSystem.js +191 -0
- package/vendor/quickjs/index.d.ts +77 -0
- package/vendor/quickjs/index.js +77 -0
- package/vendor/quickjs/loadAsyncQuickJs.d.ts +12 -0
- package/vendor/quickjs/loadAsyncQuickJs.js +66 -0
- package/vendor/quickjs/loadQuickJs.d.ts +12 -0
- package/vendor/quickjs/loadQuickJs.js +73 -0
- package/vendor/quickjs/modules/assert.d.ts +2 -0
- package/vendor/quickjs/modules/assert.js +47 -0
- package/vendor/quickjs/modules/buffer.d.ts +2 -0
- package/vendor/quickjs/modules/buffer.js +106 -0
- package/vendor/quickjs/modules/build/test-lib.js +2 -0
- package/vendor/quickjs/modules/events.d.ts +2 -0
- package/vendor/quickjs/modules/events.js +4 -0
- package/vendor/quickjs/modules/fs.d.ts +2 -0
- package/vendor/quickjs/modules/fs.js +76 -0
- package/vendor/quickjs/modules/fs_promises.d.ts +2 -0
- package/vendor/quickjs/modules/fs_promises.js +328 -0
- package/vendor/quickjs/modules/module.d.ts +2 -0
- package/vendor/quickjs/modules/module.js +33 -0
- package/vendor/quickjs/modules/nodeCompatibility/headers.d.ts +2 -0
- package/vendor/quickjs/modules/nodeCompatibility/headers.js +58 -0
- package/vendor/quickjs/modules/nodeCompatibility/request.d.ts +2 -0
- package/vendor/quickjs/modules/nodeCompatibility/request.js +5 -0
- package/vendor/quickjs/modules/nodeCompatibility/response.d.ts +2 -0
- package/vendor/quickjs/modules/nodeCompatibility/response.js +5 -0
- package/vendor/quickjs/modules/path.d.ts +2 -0
- package/vendor/quickjs/modules/path.js +504 -0
- package/vendor/quickjs/modules/process.d.ts +2 -0
- package/vendor/quickjs/modules/process.js +309 -0
- package/vendor/quickjs/modules/punycode.d.ts +2 -0
- package/vendor/quickjs/modules/punycode.js +443 -0
- package/vendor/quickjs/modules/querystring.d.ts +2 -0
- package/vendor/quickjs/modules/querystring.js +15 -0
- package/vendor/quickjs/modules/string_decoder.d.ts +2 -0
- package/vendor/quickjs/modules/string_decoder.js +223 -0
- package/vendor/quickjs/modules/timers.d.ts +2 -0
- package/vendor/quickjs/modules/timers.js +10 -0
- package/vendor/quickjs/modules/timers_promises.d.ts +2 -0
- package/vendor/quickjs/modules/timers_promises.js +40 -0
- package/vendor/quickjs/modules/url.d.ts +2 -0
- package/vendor/quickjs/modules/url.js +104 -0
- package/vendor/quickjs/modules/util.d.ts +2 -0
- package/vendor/quickjs/modules/util.js +233 -0
- package/vendor/quickjs/package.json +3 -0
- package/vendor/quickjs/sandbox/asyncVersion/createAsyncEvalCodeFunction.d.ts +4 -0
- package/vendor/quickjs/sandbox/asyncVersion/createAsyncEvalCodeFunction.js +76 -0
- package/vendor/quickjs/sandbox/asyncVersion/createAsyncValidateCodeFunction.d.ts +3 -0
- package/vendor/quickjs/sandbox/asyncVersion/createAsyncValidateCodeFunction.js +22 -0
- package/vendor/quickjs/sandbox/asyncVersion/executeAsyncSandboxFunction.d.ts +12 -0
- package/vendor/quickjs/sandbox/asyncVersion/executeAsyncSandboxFunction.js +9 -0
- package/vendor/quickjs/sandbox/asyncVersion/getAsyncModuleLoader.d.ts +4 -0
- package/vendor/quickjs/sandbox/asyncVersion/getAsyncModuleLoader.js +30 -0
- package/vendor/quickjs/sandbox/asyncVersion/modulePathNormalizerAsync.d.ts +2 -0
- package/vendor/quickjs/sandbox/asyncVersion/modulePathNormalizerAsync.js +12 -0
- package/vendor/quickjs/sandbox/asyncVersion/prepareAsyncNodeCompatibility.d.ts +3 -0
- package/vendor/quickjs/sandbox/asyncVersion/prepareAsyncNodeCompatibility.js +11 -0
- package/vendor/quickjs/sandbox/asyncVersion/prepareAsyncSandbox.d.ts +4 -0
- package/vendor/quickjs/sandbox/asyncVersion/prepareAsyncSandbox.js +10 -0
- package/vendor/quickjs/sandbox/expose/expose.d.ts +3 -0
- package/vendor/quickjs/sandbox/expose/expose.js +155 -0
- package/vendor/quickjs/sandbox/expose/isES2015Class.d.ts +1 -0
- package/vendor/quickjs/sandbox/expose/isES2015Class.js +4 -0
- package/vendor/quickjs/sandbox/expose/isObject.d.ts +1 -0
- package/vendor/quickjs/sandbox/expose/isObject.js +4 -0
- package/vendor/quickjs/sandbox/expose/pendingHostPromises.d.ts +6 -0
- package/vendor/quickjs/sandbox/expose/pendingHostPromises.js +40 -0
- package/vendor/quickjs/sandbox/getMaxIntervalAmount.d.ts +8 -0
- package/vendor/quickjs/sandbox/getMaxIntervalAmount.js +12 -0
- package/vendor/quickjs/sandbox/getMaxTimeoutAmount.d.ts +8 -0
- package/vendor/quickjs/sandbox/getMaxTimeoutAmount.js +12 -0
- package/vendor/quickjs/sandbox/handleEvalError.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleEvalError.js +21 -0
- package/vendor/quickjs/sandbox/handleToNative/handleToNative.d.ts +9 -0
- package/vendor/quickjs/sandbox/handleToNative/handleToNative.js +153 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/index.d.ts +10 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/index.js +36 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeArrayBuffer.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeArrayBuffer.js +4 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeBuffer.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeBuffer.js +16 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeDate.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeDate.js +16 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeError.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeError.js +18 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeHeaders.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeHeaders.js +17 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeMap.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeMap.js +18 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeSet.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeSet.js +16 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeURLSearchParams.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeURLSearchParams.js +17 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeUrl.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeUrl.js +17 -0
- package/vendor/quickjs/sandbox/helper.d.ts +2 -0
- package/vendor/quickjs/sandbox/helper.js +14 -0
- package/vendor/quickjs/sandbox/provide/provideConsole.d.ts +6 -0
- package/vendor/quickjs/sandbox/provide/provideConsole.js +53 -0
- package/vendor/quickjs/sandbox/provide/provideEnv.d.ts +3 -0
- package/vendor/quickjs/sandbox/provide/provideEnv.js +10 -0
- package/vendor/quickjs/sandbox/provide/provideFs.d.ts +4 -0
- package/vendor/quickjs/sandbox/provide/provideFs.js +159 -0
- package/vendor/quickjs/sandbox/provide/provideHttp.d.ts +9 -0
- package/vendor/quickjs/sandbox/provide/provideHttp.js +42 -0
- package/vendor/quickjs/sandbox/provide/provideTimingFunctions.d.ts +7 -0
- package/vendor/quickjs/sandbox/provide/provideTimingFunctions.js +119 -0
- package/vendor/quickjs/sandbox/setupFileSystem.d.ts +3 -0
- package/vendor/quickjs/sandbox/setupFileSystem.js +13 -0
- package/vendor/quickjs/sandbox/syncVersion/createEvalCodeFunction.d.ts +4 -0
- package/vendor/quickjs/sandbox/syncVersion/createEvalCodeFunction.js +76 -0
- package/vendor/quickjs/sandbox/syncVersion/createValidateCodeFunction.d.ts +3 -0
- package/vendor/quickjs/sandbox/syncVersion/createValidateCodeFunction.js +22 -0
- package/vendor/quickjs/sandbox/syncVersion/executeSandboxFunction.d.ts +12 -0
- package/vendor/quickjs/sandbox/syncVersion/executeSandboxFunction.js +9 -0
- package/vendor/quickjs/sandbox/syncVersion/getModuleLoader.d.ts +4 -0
- package/vendor/quickjs/sandbox/syncVersion/getModuleLoader.js +30 -0
- package/vendor/quickjs/sandbox/syncVersion/modulePathNormalizer.d.ts +2 -0
- package/vendor/quickjs/sandbox/syncVersion/modulePathNormalizer.js +12 -0
- package/vendor/quickjs/sandbox/syncVersion/prepareNodeCompatibility.d.ts +3 -0
- package/vendor/quickjs/sandbox/syncVersion/prepareNodeCompatibility.js +11 -0
- package/vendor/quickjs/sandbox/syncVersion/prepareSandbox.d.ts +4 -0
- package/vendor/quickjs/sandbox/syncVersion/prepareSandbox.js +10 -0
- package/vendor/quickjs/types/CodeFunctionInput.d.ts +12 -0
- package/vendor/quickjs/types/CodeFunctionInput.js +1 -0
- package/vendor/quickjs/types/ErrorResponse.d.ts +9 -0
- package/vendor/quickjs/types/ErrorResponse.js +1 -0
- package/vendor/quickjs/types/LoadQuickJsOptions.d.ts +3 -0
- package/vendor/quickjs/types/LoadQuickJsOptions.js +1 -0
- package/vendor/quickjs/types/OkResponse.d.ts +4 -0
- package/vendor/quickjs/types/OkResponse.js +1 -0
- package/vendor/quickjs/types/OkResponseCheck.d.ts +3 -0
- package/vendor/quickjs/types/OkResponseCheck.js +1 -0
- package/vendor/quickjs/types/Prettify.d.ts +3 -0
- package/vendor/quickjs/types/Prettify.js +1 -0
- package/vendor/quickjs/types/RuntimeOptions.d.ts +87 -0
- package/vendor/quickjs/types/RuntimeOptions.js +1 -0
- package/vendor/quickjs/types/SandboxEvalCode.d.ts +5 -0
- package/vendor/quickjs/types/SandboxEvalCode.js +1 -0
- package/vendor/quickjs/types/SandboxFunction.d.ts +16 -0
- package/vendor/quickjs/types/SandboxFunction.js +1 -0
- package/vendor/quickjs/types/SandboxOptions.d.ts +152 -0
- package/vendor/quickjs/types/SandboxOptions.js +1 -0
- package/vendor/quickjs/types/SandboxValidateCode.d.ts +9 -0
- package/vendor/quickjs/types/SandboxValidateCode.js +1 -0
- package/vendor/quickjs/types/Serializer.d.ts +2 -0
- package/vendor/quickjs/types/Serializer.js +1 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { IFs } from 'memfs';
|
|
2
|
+
import type { QuickJSAsyncContext, QuickJSContext, Scope } from 'quickjs-emscripten-core';
|
|
3
|
+
import type { RuntimeOptions } from '../../types/RuntimeOptions.js';
|
|
4
|
+
/**
|
|
5
|
+
* Provide http related functions
|
|
6
|
+
*/
|
|
7
|
+
export declare const provideHttp: (ctx: QuickJSContext | QuickJSAsyncContext, scope: Scope, options: RuntimeOptions, input?: {
|
|
8
|
+
fs?: IFs | undefined;
|
|
9
|
+
}) => void;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { getDefaultFetchAdapter } from '../../adapter/fetch.js';
|
|
2
|
+
import { expose } from '../expose/expose.js';
|
|
3
|
+
/**
|
|
4
|
+
* Provide http related functions
|
|
5
|
+
*/
|
|
6
|
+
export const provideHttp = (ctx, scope, options, input) => {
|
|
7
|
+
const injectUnsupported = (name) => () => {
|
|
8
|
+
throw new Error(`Not supported: ${name} has been disabled for security reasons or is not supported by the runtime`);
|
|
9
|
+
};
|
|
10
|
+
let fetchFunction = Object.assign(injectUnsupported('fetch'), {
|
|
11
|
+
preconnect: async (_url, _options) => {
|
|
12
|
+
return;
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
if (options.allowFetch) {
|
|
16
|
+
const adapter = options.fetchAdapter ?? getDefaultFetchAdapter({ fs: input?.fs });
|
|
17
|
+
fetchFunction = Object.assign(adapter, {
|
|
18
|
+
preconnect: async (_url, _options) => {
|
|
19
|
+
return;
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
expose(ctx, scope, {
|
|
24
|
+
__parseURL: (input, base) => {
|
|
25
|
+
const url = new URL(input, base);
|
|
26
|
+
return {
|
|
27
|
+
href: url.href,
|
|
28
|
+
origin: url.origin,
|
|
29
|
+
protocol: url.protocol,
|
|
30
|
+
username: url.username,
|
|
31
|
+
password: url.password,
|
|
32
|
+
host: url.host,
|
|
33
|
+
hostname: url.hostname,
|
|
34
|
+
port: url.port,
|
|
35
|
+
pathname: url.pathname,
|
|
36
|
+
hash: url.hash,
|
|
37
|
+
search: url.search,
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
fetch: fetchFunction,
|
|
41
|
+
});
|
|
42
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type QuickJSAsyncContext, type QuickJSContext } from 'quickjs-emscripten-core';
|
|
2
|
+
export declare const provideTimingFunctions: (ctx: QuickJSContext | QuickJSAsyncContext, max: {
|
|
3
|
+
maxTimeoutCount: number;
|
|
4
|
+
maxIntervalCount: number;
|
|
5
|
+
}) => {
|
|
6
|
+
dispose: () => void;
|
|
7
|
+
};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { Scope } from 'quickjs-emscripten-core';
|
|
2
|
+
export const provideTimingFunctions = (ctx, max) => {
|
|
3
|
+
const scope = new Scope();
|
|
4
|
+
const timeouts = new Map();
|
|
5
|
+
let timeoutCounter = 0;
|
|
6
|
+
const immediates = new Map();
|
|
7
|
+
let immediateCounter = 0;
|
|
8
|
+
const intervals = new Map();
|
|
9
|
+
let intervalCounter = 0;
|
|
10
|
+
const _setTimeout = ctx.newFunction('setTimeout', (vmFnHandle, timeoutHandle) => {
|
|
11
|
+
const currentCounter = timeoutCounter++;
|
|
12
|
+
if (timeouts.size + 1 > max.maxTimeoutCount) {
|
|
13
|
+
throw new Error(`Client tries to use setTimeout, which exceeds the limit of max ${max.maxTimeoutCount} concurrent running timeout functions`);
|
|
14
|
+
}
|
|
15
|
+
const vmFnHandleCopy = vmFnHandle.dup();
|
|
16
|
+
scope.manage(vmFnHandleCopy);
|
|
17
|
+
const timeout = timeoutHandle ? ctx.dump(timeoutHandle) : undefined;
|
|
18
|
+
const timeoutID = setTimeout(() => {
|
|
19
|
+
const t = timeouts.get(currentCounter);
|
|
20
|
+
if (t) {
|
|
21
|
+
clearTimeout(t);
|
|
22
|
+
timeouts.delete(currentCounter);
|
|
23
|
+
}
|
|
24
|
+
ctx.callFunction(vmFnHandleCopy, ctx.undefined);
|
|
25
|
+
}, timeout);
|
|
26
|
+
timeouts.set(currentCounter, timeoutID);
|
|
27
|
+
return ctx.newNumber(currentCounter);
|
|
28
|
+
});
|
|
29
|
+
scope.manage(_setTimeout);
|
|
30
|
+
ctx.setProp(ctx.global, 'setTimeout', _setTimeout);
|
|
31
|
+
const _clearTimeout = ctx.newFunction('clearTimeout', timeoutHandle => {
|
|
32
|
+
const id = ctx.dump(timeoutHandle);
|
|
33
|
+
timeoutHandle.dispose();
|
|
34
|
+
const t = timeouts.get(id);
|
|
35
|
+
if (t) {
|
|
36
|
+
clearTimeout(t);
|
|
37
|
+
timeouts.delete(id);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
scope.manage(_clearTimeout);
|
|
41
|
+
ctx.setProp(ctx.global, 'clearTimeout', _clearTimeout);
|
|
42
|
+
const _setImmediate = ctx.newFunction('setImmediate', vmFnHandle => {
|
|
43
|
+
const currentCounter = immediateCounter++;
|
|
44
|
+
if (timeouts.size + 1 > max.maxTimeoutCount) {
|
|
45
|
+
throw new Error(`Client tries to use setImmediate, which exceeds the limit of max ${max.maxTimeoutCount} concurrent running timeout functions`);
|
|
46
|
+
}
|
|
47
|
+
const vmFnHandleCopy = vmFnHandle.dup();
|
|
48
|
+
scope.manage(vmFnHandleCopy);
|
|
49
|
+
const timeoutID = setTimeout(() => {
|
|
50
|
+
const t = immediates.get(currentCounter);
|
|
51
|
+
if (t) {
|
|
52
|
+
clearTimeout(t);
|
|
53
|
+
immediates.delete(currentCounter);
|
|
54
|
+
}
|
|
55
|
+
ctx.callFunction(vmFnHandleCopy, ctx.undefined);
|
|
56
|
+
}, 0);
|
|
57
|
+
immediates.set(currentCounter, timeoutID);
|
|
58
|
+
return ctx.newNumber(currentCounter);
|
|
59
|
+
});
|
|
60
|
+
scope.manage(_setImmediate);
|
|
61
|
+
ctx.setProp(ctx.global, 'setImmediate', _setImmediate);
|
|
62
|
+
const _clearImmediate = ctx.newFunction('clearImmediate', idHandle => {
|
|
63
|
+
const id = ctx.dump(idHandle);
|
|
64
|
+
idHandle.dispose();
|
|
65
|
+
const t = immediates.get(id);
|
|
66
|
+
if (t) {
|
|
67
|
+
clearTimeout(t);
|
|
68
|
+
immediates.delete(id);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
scope.manage(_clearImmediate);
|
|
72
|
+
ctx.setProp(ctx.global, 'clearImmediate', _clearImmediate);
|
|
73
|
+
const _setInterval = ctx.newFunction('setInterval', (vmFnHandle, intervalHandle) => {
|
|
74
|
+
const currentCounter = intervalCounter++;
|
|
75
|
+
if (intervals.size + 1 > max.maxIntervalCount) {
|
|
76
|
+
throw new Error(`Client tries to use setInterval, which exceeds the limit of max ${max.maxIntervalCount} concurrent running interval functions`);
|
|
77
|
+
}
|
|
78
|
+
const vmFnHandleCopy = vmFnHandle.dup();
|
|
79
|
+
scope.manage(vmFnHandleCopy);
|
|
80
|
+
const interval = ctx.dump(intervalHandle);
|
|
81
|
+
const intervalID = setInterval(() => {
|
|
82
|
+
ctx.callFunction(vmFnHandleCopy, ctx.undefined);
|
|
83
|
+
}, interval);
|
|
84
|
+
intervals.set(currentCounter, intervalID);
|
|
85
|
+
return ctx.newNumber(currentCounter);
|
|
86
|
+
});
|
|
87
|
+
scope.manage(_setInterval);
|
|
88
|
+
ctx.setProp(ctx.global, 'setInterval', _setInterval);
|
|
89
|
+
const _clearInterval = ctx.newFunction('clearInterval', intervalHandle => {
|
|
90
|
+
const id = ctx.dump(intervalHandle);
|
|
91
|
+
intervalHandle.dispose();
|
|
92
|
+
const t = intervals.get(id);
|
|
93
|
+
if (t) {
|
|
94
|
+
clearInterval(t);
|
|
95
|
+
intervals.delete(id);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
scope.manage(_clearInterval);
|
|
99
|
+
ctx.setProp(ctx.global, 'clearInterval', _clearInterval);
|
|
100
|
+
const dispose = () => {
|
|
101
|
+
for (const [_key, value] of timeouts) {
|
|
102
|
+
clearTimeout(value);
|
|
103
|
+
}
|
|
104
|
+
timeouts.clear();
|
|
105
|
+
timeoutCounter = 0;
|
|
106
|
+
for (const [_key, value] of immediates) {
|
|
107
|
+
clearTimeout(value);
|
|
108
|
+
}
|
|
109
|
+
immediates.clear();
|
|
110
|
+
immediateCounter = 0;
|
|
111
|
+
for (const [_key, value] of intervals) {
|
|
112
|
+
clearInterval(value);
|
|
113
|
+
}
|
|
114
|
+
intervals.clear();
|
|
115
|
+
intervalCounter = 0;
|
|
116
|
+
scope.dispose();
|
|
117
|
+
};
|
|
118
|
+
return { dispose };
|
|
119
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createVirtualFileSystem } from '../createVirtualFileSystem.js';
|
|
2
|
+
const isMountedFs = (input) => typeof input === 'object' &&
|
|
3
|
+
input !== null &&
|
|
4
|
+
'readFileSync' in input &&
|
|
5
|
+
typeof input.readFileSync === 'function' &&
|
|
6
|
+
'existsSync' in input &&
|
|
7
|
+
typeof input.existsSync === 'function';
|
|
8
|
+
export const setupFileSystem = (runtimeOptions) => {
|
|
9
|
+
if (runtimeOptions.mountFs && isMountedFs(runtimeOptions.mountFs)) {
|
|
10
|
+
return runtimeOptions.mountFs;
|
|
11
|
+
}
|
|
12
|
+
return createVirtualFileSystem(runtimeOptions).fs;
|
|
13
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Scope } from 'quickjs-emscripten-core';
|
|
2
|
+
import type { CodeFunctionInput } from '../../types/CodeFunctionInput.js';
|
|
3
|
+
import type { SandboxEvalCode } from '../../types/SandboxEvalCode.js';
|
|
4
|
+
export declare const createEvalCodeFunction: (input: CodeFunctionInput, scope: Scope) => SandboxEvalCode;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { createTimeInterval } from '../../createTimeInterval.js';
|
|
2
|
+
import { rejectAndFlushPendingHostPromises } from '../expose/pendingHostPromises.js';
|
|
3
|
+
import { getMaxIntervalAmount } from '../getMaxIntervalAmount.js';
|
|
4
|
+
import { getMaxTimeoutAmount } from '../getMaxTimeoutAmount.js';
|
|
5
|
+
import { handleEvalError } from '../handleEvalError.js';
|
|
6
|
+
import { handleToNative } from '../handleToNative/handleToNative.js';
|
|
7
|
+
import { provideTimingFunctions } from '../provide/provideTimingFunctions.js';
|
|
8
|
+
export const createEvalCodeFunction = (input, scope) => {
|
|
9
|
+
const { ctx, sandboxOptions, transpileFile } = input;
|
|
10
|
+
return async (code, filename = '/src/index.js', evalOptions) => {
|
|
11
|
+
const eventLoopinterval = createTimeInterval(() => ctx.runtime.executePendingJobs(), 0);
|
|
12
|
+
const timeoutMs = sandboxOptions.executionTimeout ?? 0;
|
|
13
|
+
let timeoutId;
|
|
14
|
+
let nativePromise;
|
|
15
|
+
let timedOut = false;
|
|
16
|
+
const { dispose: disposeTimer } = provideTimingFunctions(ctx, {
|
|
17
|
+
maxTimeoutCount: getMaxTimeoutAmount(sandboxOptions),
|
|
18
|
+
maxIntervalCount: getMaxIntervalAmount(sandboxOptions),
|
|
19
|
+
});
|
|
20
|
+
const disposeStep = () => {
|
|
21
|
+
if (timeoutId) {
|
|
22
|
+
clearTimeout(timeoutId);
|
|
23
|
+
}
|
|
24
|
+
eventLoopinterval?.clear();
|
|
25
|
+
disposeTimer();
|
|
26
|
+
};
|
|
27
|
+
try {
|
|
28
|
+
const jsCode = transpileFile(code);
|
|
29
|
+
const evalResult = ctx.evalCode(jsCode, filename, {
|
|
30
|
+
strict: true,
|
|
31
|
+
strip: false,
|
|
32
|
+
backtraceBarrier: true,
|
|
33
|
+
...evalOptions,
|
|
34
|
+
type: 'module',
|
|
35
|
+
});
|
|
36
|
+
const handle = scope.manage(ctx.unwrapResult(evalResult));
|
|
37
|
+
const native = handleToNative(ctx, handle, scope);
|
|
38
|
+
nativePromise = (async () => {
|
|
39
|
+
const res = await native;
|
|
40
|
+
return res.default;
|
|
41
|
+
})();
|
|
42
|
+
const result = await Promise.race([
|
|
43
|
+
nativePromise,
|
|
44
|
+
new Promise((_resolve, reject) => {
|
|
45
|
+
if (timeoutMs > 0) {
|
|
46
|
+
timeoutId = setTimeout(() => {
|
|
47
|
+
timedOut = true;
|
|
48
|
+
const err = new Error('The script execution has exceeded the maximum allowed time limit.');
|
|
49
|
+
err.name = 'ExecutionTimeout';
|
|
50
|
+
reject(err);
|
|
51
|
+
}, timeoutMs);
|
|
52
|
+
}
|
|
53
|
+
}),
|
|
54
|
+
]);
|
|
55
|
+
return { ok: true, data: result };
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
return handleEvalError(err);
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
if (timedOut && nativePromise) {
|
|
62
|
+
// Reject unresolved host-injected promises to avoid leaving QuickJS promises
|
|
63
|
+
// pending while disposing the runtime after timeout.
|
|
64
|
+
await rejectAndFlushPendingHostPromises(ctx);
|
|
65
|
+
// Force-fast interrupt handling and give pending guest jobs a short window to settle.
|
|
66
|
+
ctx.runtime.setInterruptHandler(() => true);
|
|
67
|
+
const cleanupWait = Math.min(Math.max(timeoutMs, 50), 1000);
|
|
68
|
+
await Promise.race([
|
|
69
|
+
nativePromise.catch(() => undefined),
|
|
70
|
+
new Promise(resolve => setTimeout(resolve, cleanupWait)),
|
|
71
|
+
]);
|
|
72
|
+
}
|
|
73
|
+
disposeStep();
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { handleEvalError } from '../handleEvalError.js';
|
|
2
|
+
export const createValidateCodeFunction = (input) => {
|
|
3
|
+
const { ctx } = input;
|
|
4
|
+
return async (code, filename = '/src/index.js', evalOptions) => {
|
|
5
|
+
try {
|
|
6
|
+
ctx
|
|
7
|
+
.unwrapResult(ctx.evalCode(code, filename, {
|
|
8
|
+
strict: true,
|
|
9
|
+
strip: true,
|
|
10
|
+
backtraceBarrier: true,
|
|
11
|
+
...evalOptions,
|
|
12
|
+
type: 'module',
|
|
13
|
+
compileOnly: true,
|
|
14
|
+
}))
|
|
15
|
+
.dispose();
|
|
16
|
+
return { ok: true };
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
return handleEvalError(err);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IFs } from 'memfs';
|
|
2
|
+
import type { QuickJSContext, Scope } from 'quickjs-emscripten-core';
|
|
3
|
+
import type { SandboxFunction } from '../../types/SandboxFunction.js';
|
|
4
|
+
import type { SandboxOptions } from '../../types/SandboxOptions.js';
|
|
5
|
+
export declare const executeSandboxFunction: <T>(input: {
|
|
6
|
+
ctx: QuickJSContext;
|
|
7
|
+
fs: IFs;
|
|
8
|
+
scope: Scope;
|
|
9
|
+
sandboxOptions: SandboxOptions;
|
|
10
|
+
sandboxedFunction: SandboxFunction<T>;
|
|
11
|
+
transpileFile: (input: string) => string;
|
|
12
|
+
}) => Promise<T>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createEvalCodeFunction } from './createEvalCodeFunction.js';
|
|
2
|
+
import { createValidateCodeFunction } from './createValidateCodeFunction.js';
|
|
3
|
+
export const executeSandboxFunction = async (input) => {
|
|
4
|
+
const { ctx, sandboxOptions, sandboxedFunction, fs, transpileFile } = input;
|
|
5
|
+
const opt = { ctx, sandboxOptions, transpileFile };
|
|
6
|
+
const evalCode = createEvalCodeFunction(opt, input.scope);
|
|
7
|
+
const validateCode = createValidateCodeFunction(opt);
|
|
8
|
+
return await sandboxedFunction({ ctx, evalCode, validateCode, mountedFs: fs });
|
|
9
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
export const getModuleLoader = (fs, _runtimeOptions) => {
|
|
3
|
+
const moduleLoader = (inputName, _context) => {
|
|
4
|
+
let name = inputName;
|
|
5
|
+
// if it does not exist
|
|
6
|
+
if (!fs.existsSync(name)) {
|
|
7
|
+
// try to add the .js extension
|
|
8
|
+
if (fs.existsSync(`${name}.js`)) {
|
|
9
|
+
name = `${name}.js`;
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
return { error: new Error(`Module '${inputName}' not installed or available`) };
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
// if it is a folder, we need to use the index.js file
|
|
16
|
+
if (fs.lstatSync(name).isDirectory()) {
|
|
17
|
+
name = join(name, 'index.js');
|
|
18
|
+
if (!fs.existsSync(name)) {
|
|
19
|
+
return { error: new Error(`Module '${inputName}' not installed or available`) };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// workaround: as we can not provide the real import.meta.url functionality, we replace it dynamically with the current value string
|
|
23
|
+
const value = fs.readFileSync(name)?.toString().replaceAll('import.meta.url', `'file://${name}'`);
|
|
24
|
+
if (!value) {
|
|
25
|
+
return { error: new Error(`Module '${name}' not installed or available`) };
|
|
26
|
+
}
|
|
27
|
+
return { value };
|
|
28
|
+
};
|
|
29
|
+
return moduleLoader;
|
|
30
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { join, resolve } from 'node:path';
|
|
2
|
+
export const modulePathNormalizer = (baseName, requestedName) => {
|
|
3
|
+
// relative import
|
|
4
|
+
if (requestedName.startsWith('.')) {
|
|
5
|
+
const parts = baseName.split('/');
|
|
6
|
+
parts.pop();
|
|
7
|
+
return resolve(`/${parts.join('/')}`, requestedName);
|
|
8
|
+
}
|
|
9
|
+
// module import
|
|
10
|
+
const moduleName = requestedName.replace('node:', '');
|
|
11
|
+
return join('/node_modules', moduleName);
|
|
12
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const prepareNodeCompatibility = (vm, sandboxOptions) => {
|
|
2
|
+
vm.unwrapResult(vm.evalCode(`
|
|
3
|
+
import 'node:buffer';
|
|
4
|
+
import 'node:util';
|
|
5
|
+
import 'node:url';
|
|
6
|
+
import '@node_compatibility/headers';
|
|
7
|
+
import '@node_compatibility/request';
|
|
8
|
+
import '@node_compatibility/response';
|
|
9
|
+
${sandboxOptions.enableTestUtils ? "import 'test'" : ''}
|
|
10
|
+
`, undefined, { type: 'module' })).dispose();
|
|
11
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { IFs } from 'memfs';
|
|
2
|
+
import type { QuickJSContext, Scope } from 'quickjs-emscripten-core';
|
|
3
|
+
import type { SandboxBaseOptions } from '../../types/SandboxOptions.js';
|
|
4
|
+
export declare const prepareSandbox: (ctx: QuickJSContext, scope: Scope, sandboxOptions: SandboxBaseOptions, fs: IFs) => void;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { provideConsole } from './../provide/provideConsole.js';
|
|
2
|
+
import { provideEnv } from '../provide/provideEnv.js';
|
|
3
|
+
import { provideFs } from '../provide/provideFs.js';
|
|
4
|
+
import { provideHttp } from '../provide/provideHttp.js';
|
|
5
|
+
export const prepareSandbox = (ctx, scope, sandboxOptions, fs) => {
|
|
6
|
+
provideFs(ctx, scope, sandboxOptions, fs);
|
|
7
|
+
provideConsole(ctx, scope, sandboxOptions);
|
|
8
|
+
provideEnv(ctx, scope, sandboxOptions);
|
|
9
|
+
provideHttp(ctx, scope, sandboxOptions, { fs: sandboxOptions.allowFs ? fs : undefined });
|
|
10
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { QuickJSAsyncContext, QuickJSContext } from 'quickjs-emscripten-core';
|
|
2
|
+
import type { SandboxAsyncOptions, SandboxOptions } from './SandboxOptions.js';
|
|
3
|
+
export type CodeFunctionInput = {
|
|
4
|
+
ctx: QuickJSContext;
|
|
5
|
+
sandboxOptions: SandboxOptions;
|
|
6
|
+
transpileFile: (input: string) => string;
|
|
7
|
+
};
|
|
8
|
+
export type CodeFunctionAsyncInput = {
|
|
9
|
+
ctx: QuickJSAsyncContext;
|
|
10
|
+
sandboxOptions: SandboxAsyncOptions;
|
|
11
|
+
transpileFile: (input: string) => string;
|
|
12
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { IFs, NestedDirectoryJSON } from 'memfs';
|
|
2
|
+
export type RuntimeOptions = {
|
|
3
|
+
/**
|
|
4
|
+
* The maximum time in seconds a script can run.
|
|
5
|
+
* Unset or set to 0 for unlimited execution time.
|
|
6
|
+
*/
|
|
7
|
+
executionTimeout?: number;
|
|
8
|
+
/**
|
|
9
|
+
* Mount a virtual file system
|
|
10
|
+
* @link https://github.com/streamich/memfs
|
|
11
|
+
*/
|
|
12
|
+
mountFs?: NestedDirectoryJSON | IFs;
|
|
13
|
+
/**
|
|
14
|
+
* Mount custom node_modules in a virtual file system
|
|
15
|
+
* @link https://github.com/streamich/memfs
|
|
16
|
+
*/
|
|
17
|
+
nodeModules?: NestedDirectoryJSON;
|
|
18
|
+
/**
|
|
19
|
+
* Enable file capabilities
|
|
20
|
+
* If enabled, the package node:fs becomes available
|
|
21
|
+
*/
|
|
22
|
+
allowFs?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Allow code to make http(s) calls.
|
|
25
|
+
* When enabled, the global fetch will be available
|
|
26
|
+
*/
|
|
27
|
+
allowFetch?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* The custom fetch adapter provided as host function in the QuickJS runtime
|
|
30
|
+
*/
|
|
31
|
+
fetchAdapter?: typeof fetch;
|
|
32
|
+
/**
|
|
33
|
+
* Includes test framework
|
|
34
|
+
* If enabled, the packages chai and mocha become available
|
|
35
|
+
* They are registered global
|
|
36
|
+
*/
|
|
37
|
+
enableTestUtils?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Per default, the console log inside of QuickJS is passed to the host console log.
|
|
40
|
+
* Here, you can customize the handling and provide your own logging methods.
|
|
41
|
+
*/
|
|
42
|
+
console?: {
|
|
43
|
+
log?: (message?: unknown, ...optionalParams: unknown[]) => void;
|
|
44
|
+
error?: (message?: unknown, ...optionalParams: unknown[]) => void;
|
|
45
|
+
warn?: (message?: unknown, ...optionalParams: unknown[]) => void;
|
|
46
|
+
info?: (message?: unknown, ...optionalParams: unknown[]) => void;
|
|
47
|
+
debug?: (message?: unknown, ...optionalParams: unknown[]) => void;
|
|
48
|
+
trace?: (message?: unknown, ...optionalParams: unknown[]) => void;
|
|
49
|
+
assert?: (condition?: boolean, ...data: unknown[]) => void;
|
|
50
|
+
count?: (label?: string) => void;
|
|
51
|
+
countReset?: (label?: string) => void;
|
|
52
|
+
dir?: (item?: unknown, options?: object) => void;
|
|
53
|
+
dirxml?: (...data: unknown[]) => void;
|
|
54
|
+
group?: (...label: unknown[]) => void;
|
|
55
|
+
groupCollapsed?: (...label: unknown[]) => void;
|
|
56
|
+
groupEnd?: () => void;
|
|
57
|
+
table?: (tabularData?: unknown, properties?: string[]) => void;
|
|
58
|
+
time?: (label?: string) => void;
|
|
59
|
+
timeEnd?: (label?: string) => void;
|
|
60
|
+
timeLog?: (label?: string, ...data: unknown[]) => void;
|
|
61
|
+
clear?: () => void;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Key-value list of ENV vars, which should be available in QuickJS
|
|
65
|
+
* It is not limited to primitives like string and numbers.
|
|
66
|
+
* Objects, arrays and functions can be provided as well.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```js
|
|
70
|
+
* // in config
|
|
71
|
+
* {
|
|
72
|
+
* env: {
|
|
73
|
+
* My_ENV: 'my var'
|
|
74
|
+
* }
|
|
75
|
+
* }
|
|
76
|
+
*
|
|
77
|
+
* // inside of QuickJS
|
|
78
|
+
* console.log(env.My_ENV) // outputs: my var
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
env?: Record<string, unknown>;
|
|
82
|
+
/**
|
|
83
|
+
* The object is synchronized between host and guest system.
|
|
84
|
+
* This means, the values on the host, can be set by the guest system
|
|
85
|
+
*/
|
|
86
|
+
dangerousSync?: Record<string, unknown>;
|
|
87
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ContextEvalOptions } from 'quickjs-emscripten-core';
|
|
2
|
+
import type { ErrorResponse } from './ErrorResponse.js';
|
|
3
|
+
import type { OkResponse } from './OkResponse.js';
|
|
4
|
+
import type { Prettify } from './Prettify.js';
|
|
5
|
+
export type SandboxEvalCode<T = unknown> = (code: string, filename?: string, options?: Prettify<Omit<ContextEvalOptions, 'type'>>) => Promise<OkResponse<T> | ErrorResponse>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { IFs } from 'memfs';
|
|
2
|
+
import type { QuickJSAsyncContext, QuickJSContext } from 'quickjs-emscripten-core';
|
|
3
|
+
import type { SandboxEvalCode } from './SandboxEvalCode.js';
|
|
4
|
+
import type { SandboxValidateCode } from './SandboxValidateCode.js';
|
|
5
|
+
export type SandboxFunction<T = any> = (sandbox: {
|
|
6
|
+
ctx: QuickJSContext;
|
|
7
|
+
evalCode: SandboxEvalCode;
|
|
8
|
+
validateCode: SandboxValidateCode;
|
|
9
|
+
mountedFs: IFs;
|
|
10
|
+
}) => Promise<T>;
|
|
11
|
+
export type AsyncSandboxFunction<T = any> = (sandbox: {
|
|
12
|
+
ctx: QuickJSAsyncContext;
|
|
13
|
+
evalCode: SandboxEvalCode;
|
|
14
|
+
validateCode: SandboxValidateCode;
|
|
15
|
+
mountedFs: IFs;
|
|
16
|
+
}) => Promise<T>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|