feat: removed isolated-vm sandbox

This commit is contained in:
Anoop M D
2024-08-19 11:00:27 +05:30
parent 126c648d7d
commit 1bf3a15784
21 changed files with 71 additions and 884 deletions

77
package-lock.json generated
View File

@@ -4303,6 +4303,43 @@
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
"dev": true
},
"node_modules/@jitl/quickjs-ffi-types": {
"version": "0.29.2",
"resolved": "https://registry.npmjs.org/@jitl/quickjs-ffi-types/-/quickjs-ffi-types-0.29.2.tgz",
"integrity": "sha512-069uQTiEla2PphXg6UpyyJ4QXHkTj3S9TeXgaMCd8NDYz3ODBw5U/rkg6fhuU8SMpoDrWjEzybmV5Mi2Pafb5w=="
},
"node_modules/@jitl/quickjs-wasmfile-debug-asyncify": {
"version": "0.29.2",
"resolved": "https://registry.npmjs.org/@jitl/quickjs-wasmfile-debug-asyncify/-/quickjs-wasmfile-debug-asyncify-0.29.2.tgz",
"integrity": "sha512-YdRw2414pFkxzyyoJGv81Grbo9THp/5athDMKipaSBNNQvFE9FGRrgE9tt2DT2mhNnBx1kamtOGj0dX84Yy9bg==",
"dependencies": {
"@jitl/quickjs-ffi-types": "0.29.2"
}
},
"node_modules/@jitl/quickjs-wasmfile-debug-sync": {
"version": "0.29.2",
"resolved": "https://registry.npmjs.org/@jitl/quickjs-wasmfile-debug-sync/-/quickjs-wasmfile-debug-sync-0.29.2.tgz",
"integrity": "sha512-VgisubjyPMWEr44g+OU0QWGyIxu7VkApkLHMxdORX351cw22aLTJ+Z79DJ8IVrTWc7jh4CBPsaK71RBQDuVB7w==",
"dependencies": {
"@jitl/quickjs-ffi-types": "0.29.2"
}
},
"node_modules/@jitl/quickjs-wasmfile-release-asyncify": {
"version": "0.29.2",
"resolved": "https://registry.npmjs.org/@jitl/quickjs-wasmfile-release-asyncify/-/quickjs-wasmfile-release-asyncify-0.29.2.tgz",
"integrity": "sha512-sf3luCPr8wBVmGV6UV8Set+ie8wcO6mz5wMvDVO0b90UVCKfgnx65A1JfeA+zaSGoaFyTZ3sEpXSGJU+6qJmLw==",
"dependencies": {
"@jitl/quickjs-ffi-types": "0.29.2"
}
},
"node_modules/@jitl/quickjs-wasmfile-release-sync": {
"version": "0.29.2",
"resolved": "https://registry.npmjs.org/@jitl/quickjs-wasmfile-release-sync/-/quickjs-wasmfile-release-sync-0.29.2.tgz",
"integrity": "sha512-UFIcbY3LxBRUjEqCHq3Oa6bgX5znt51V5NQck8L2US4u989ErasiMLUjmhq6UPC837Sjqu37letEK/ZpqlJ7aA==",
"dependencies": {
"@jitl/quickjs-ffi-types": "0.29.2"
}
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
@@ -18110,6 +18147,29 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/quickjs-emscripten": {
"version": "0.29.2",
"resolved": "https://registry.npmjs.org/quickjs-emscripten/-/quickjs-emscripten-0.29.2.tgz",
"integrity": "sha512-SlvkvyZgarReu2nr4rkf+xz1vN0YDUz7sx4WHz8LFtK6RNg4/vzAGcFjE7nfHYBEbKrzfIWvKnMnxZkctQ898w==",
"dependencies": {
"@jitl/quickjs-wasmfile-debug-asyncify": "0.29.2",
"@jitl/quickjs-wasmfile-debug-sync": "0.29.2",
"@jitl/quickjs-wasmfile-release-asyncify": "0.29.2",
"@jitl/quickjs-wasmfile-release-sync": "0.29.2",
"quickjs-emscripten-core": "0.29.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/quickjs-emscripten-core": {
"version": "0.29.2",
"resolved": "https://registry.npmjs.org/quickjs-emscripten-core/-/quickjs-emscripten-core-0.29.2.tgz",
"integrity": "sha512-jEAiURW4jGqwO/fW01VwlWqa2G0AJxnN5FBy1xnVu8VIVhVhiaxUfCe+bHqS6zWzfjFm86HoO40lzpteusvyJA==",
"dependencies": {
"@jitl/quickjs-ffi-types": "0.29.2"
}
},
"node_modules/randombytes": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.3.tgz",
@@ -22568,7 +22628,6 @@
"packages/bruno-js": {
"name": "@usebruno/js",
"version": "0.12.0",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@usebruno/common": "0.1.0",
@@ -22581,13 +22640,13 @@
"chai": "^4.3.7",
"chai-string": "^1.5.0",
"crypto-js": "^4.1.1",
"isolated-vm": "4.6.0",
"json-query": "^2.2.2",
"lodash": "^4.17.21",
"moment": "^2.29.4",
"nanoid": "3.3.4",
"node-fetch": "2.*",
"node-fetch": "^2.7.0",
"node-vault": "^0.10.2",
"quickjs-emscripten": "^0.29.2",
"uuid": "^9.0.0"
},
"devDependencies": {
@@ -22608,18 +22667,6 @@
"@n8n/vm2": "^3.9.23"
}
},
"packages/bruno-js/node_modules/isolated-vm": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/isolated-vm/-/isolated-vm-4.6.0.tgz",
"integrity": "sha512-MEnfC/54q5PED3VJ9UJYJPOlU6mYFHS3ivR9E8yeNNBEFRFUNBnY0xO4Rj3D/SOtFKPNmsQp9NWUYSKZqAoZiA==",
"hasInstallScript": true,
"dependencies": {
"prebuild-install": "^7.1.1"
},
"engines": {
"node": ">=16.0.0"
}
},
"packages/bruno-lang": {
"name": "@usebruno/lang",
"version": "0.12.0",

View File

@@ -12,10 +12,7 @@
},
"scripts": {
"test": "jest --testPathIgnorePatterns test.js",
"sandbox:bundle-libraries": "node ./src/sandbox/bundle-libraries.js",
"isolated-vm:install": "cd ./node_modules/isolated-vm && npm install",
"isolated-vm:prebuild:dev": "node ./scripts/prebuild-isolated-vm-for-dev.js",
"isolated-vm:prebuild:prod": "node ./scripts/prebuild-isolated-vm-for-prod-builds.js"
"sandbox:bundle-libraries": "node ./src/sandbox/bundle-libraries.js"
},
"dependencies": {
"@usebruno/common": "0.1.0",
@@ -28,7 +25,6 @@
"chai": "^4.3.7",
"chai-string": "^1.5.0",
"crypto-js": "^4.1.1",
"isolated-vm": "4.6.0",
"json-query": "^2.2.2",
"lodash": "^4.17.21",
"moment": "^2.29.4",

View File

@@ -1,11 +0,0 @@
const { execSync } = require('child_process');
const os = require('os');
const platform = os.platform();
const arch = os.arch();
const target = '23.3.3';
const command = `cd ./node_modules/isolated-vm && rm -rf prebuilds && mkdir prebuilds && npm run prebuild -- --platform=${platform} --arch=${arch} --target=${target} --runtime=electron`;
console.log(`Running command: ${command}`);
execSync(command, { stdio: 'inherit' });

View File

@@ -1,21 +0,0 @@
const { execSync } = require('child_process');
const darwin_x64 = `cd ./node_modules/isolated-vm && npm run prebuild -- --platform=darwin --arch=x64 --target=21.1.1 --runtime=electron`;
const darwin_arm64 = `cd ./node_modules/isolated-vm && npm run prebuild -- --platform=darwin --arch=arm64 --target=21.1.1 --runtime=electron`;
const linux_x64 = `cd ./node_modules/isolated-vm && npm run prebuild -- --platform=linux --arch=x64 --target=21.1.1 --runtime=electron`;
const linux_arm64 = `cd ./node_modules/isolated-vm && npm run prebuild -- --platform=linux --arch=arm64 --target=21.1.1 --runtime=electron`;
const win32_x64 = `cd ./node_modules/isolated-vm && npm run prebuild -- --platform=win32 --arch=x64 --target=21.1.1 --runtime=electron`;
const win32_arm64 = `cd ./node_modules/isolated-vm && npm run prebuild -- --platform=win32 --arch=arm64 --target=21.1.1 --runtime=electron`;
console.log(`Running command: ${darwin_x64}`);
execSync(darwin_x64, { stdio: 'inherit' });
console.log(`Running command: ${darwin_arm64}`);
execSync(darwin_arm64, { stdio: 'inherit' });
console.log(`Running command: ${linux_x64}`);
execSync(linux_x64, { stdio: 'inherit' });
console.log(`Running command: ${linux_arm64}`);
execSync(linux_arm64, { stdio: 'inherit' });
console.log(`Running command: ${win32_x64}`);
execSync(win32_x64, { stdio: 'inherit' });
console.log(`Running command: ${win32_arm64}`);
execSync(win32_arm64, { stdio: 'inherit' });

View File

@@ -92,9 +92,7 @@ class ScriptRuntime {
if (this.runtime === 'quickjs') {
await executeQuickJsVmAsync({
script: script,
context: context,
modules: {},
scriptType: 'jsScript'
context: context
});
return {
@@ -205,9 +203,7 @@ class ScriptRuntime {
if (this.runtime === 'quickjs') {
await executeQuickJsVmAsync({
script: script,
context: context,
modules: {},
scriptType: 'jsScript'
context: context
});
return {

View File

@@ -111,9 +111,7 @@ class TestRuntime {
if (this.runtime === 'quickjs') {
await executeQuickJsVmAsync({
script: testsFile,
context: context,
modules: {},
scriptType: 'jsScript'
context: context
});
} else {
// default runtime is vm2

View File

@@ -1,167 +0,0 @@
const ivm = require('isolated-vm');
const addBruShimToContext = require('./shims/bru');
const addBrunoRequestShimToContext = require('./shims/bruno-request');
const addConsoleShimToContext = require('./shims/console');
const addBrunoResponseShimToContext = require('./shims/bruno-response');
const addTestShimToContext = require('./shims/test');
const addLibraryShimsToContext = require('./shims/lib');
// execute `npm run build:isolated-vm:inbuilt-modules` if the below file doesn't exist
const getBundledCode = require('../bundle-browser-rollup');
const addSleepShimToContext = require('./shims/sleep');
const toNumber = (value) => {
const num = Number(value);
return Number.isInteger(num) ? parseInt(value, 10) : parseFloat(value);
};
const executeInIsolatedVMStrict = ({ script: externalScript, context: externalContext, scriptType = 'script' }) => {
if (!isNaN(Number(externalScript))) {
return Number(externalScript);
}
let result;
const isolate = new ivm.Isolate();
try {
const context = isolate.createContextSync();
context.global.setSync('global', context.global.derefInto());
const { bru, req, res } = externalContext;
context.evalSync(`
let bru = {};
let req = {};
let res = {};
`);
bru && addBruShimToContext(context, bru);
req && addBrunoRequestShimToContext(context, req);
res && addBrunoResponseShimToContext(context, res);
context.global.setSync('setResult', function (arg) {
result = arg;
});
const templateLiteralText = `
let value = \`${externalScript}\`;
setResult(value);
`;
const jsExpressionText = `
let value = ${externalScript};
setResult(value);
`;
let scriptText = scriptType === 'template-literal' ? templateLiteralText : jsExpressionText;
const script = isolate.compileScriptSync(scriptText);
script.runSync(context);
return result;
} catch (error) {
console.error('Error executing the script!', error);
}
isolate.dispose();
};
const executeInIsolatedVMAsync = async ({
script: externalScript,
context: externalContext,
modules = {},
scriptType = 'script'
}) => {
if (!isNaN(Number(externalScript))) {
return toNumber(externalScript);
}
let result;
const isolate = new ivm.Isolate();
try {
const context = await isolate.createContext();
await context.global.set('global', context.global.derefInto());
context.evalSync(`
let bru = {};
let req = {};
let res = {};
let console = {};
global.requireObject = {};
`);
context.global.setSync('log', function (...args) {
console.debug(...args);
});
try {
const bundledCode = getBundledCode?.toString() || '';
await context.eval(`(${bundledCode})()`);
} catch (err) {
console.debug('Error bundling libraries', err);
}
const { bru, req, res, test, __brunoTestResults, console: consoleFn } = externalContext;
bru && addBruShimToContext(context, bru);
req && addBrunoRequestShimToContext(context, req);
res && addBrunoResponseShimToContext(context, res);
consoleFn && addConsoleShimToContext(context, consoleFn);
addSleepShimToContext(context);
await context.eval(
`
global.require = (module) => {
return global.requireObject[module];
}
`
);
await addLibraryShimsToContext(context);
test && __brunoTestResults && (await addTestShimToContext(context, __brunoTestResults));
context.global.setSync('setResult', function (arg) {
result = arg;
});
const jsScriptText = `
new Promise(async (resolve, reject) => {
// modify the setTimeout function with the shim to work-around the callback-function clone issues
setTimeout = global.setTimeout;
console?.debug && console.debug('isolated-vm:execution-start:');
try {
${externalScript}
} catch (error) {
console?.debug && console.debug('isolated-vm:execution-end:with-error', error?.message);
}
console?.debug && console.debug('isolated-vm:execution-end:');
resolve();
});
`;
const templateLiteralText = `
let value = \`${externalScript}\`;
setResult(value);
`;
const jsExpressionText = `
let value = ${externalScript};
setResult(value);
`;
let scriptText =
scriptType === 'template-literal'
? templateLiteralText
: scriptType === 'expression'
? jsExpressionText
: jsScriptText;
const script = await isolate.compileScript(scriptText);
await script.run(context);
return result;
} catch (error) {
console.error('Error executing the script!', error);
}
isolate.dispose();
};
module.exports = {
executeInIsolatedVMStrict,
executeInIsolatedVMAsync
};

View File

@@ -1,59 +0,0 @@
const addBruShimToContext = (context, bru) => {
context.global.setSync('cwd', function () {
return bru.cwd();
});
context.global.setSync('getEnvName', function () {
return bru.getEnvName();
});
context.global.setSync('getProcessEnv', function (key) {
return bru.getProcessEnv(key);
});
context.global.setSync('getEnvVar', function (key) {
return bru.getEnvVar(key);
});
context.global.setSync('setEnvVar', function (key, value) {
bru.setEnvVar(key, value);
});
context.global.setSync('setVar', function (key, value) {
bru.setVar(key, value);
});
context.global.setSync('getVar', function (key) {
return bru.getVar(key);
});
context.global.setSync('setNextRequest', function (nextRequest) {
bru.setNextRequest(nextRequest);
});
context.global.setSync('visualize', function (htmlString) {
bru.visualize(htmlString);
});
context.global.setSync('getSecretVar', function (key) {
return bru.getSecretVar(key);
});
context.evalSync(`
bru = {
...bru || {},
cwd: global.cwd,
getEnvName: global.getEnvName,
getProcessEnv: global.getProcessEnv,
getEnvVar: global.getEnvVar,
setEnvVar: global.setEnvVar,
setVar: global.setVar,
getVar: global.getVar,
setNextRequest: global.setNextRequest,
visualize: global.visualize,
getSecretVar: global.getSecretVar
}
`);
};
module.exports = addBruShimToContext;

View File

@@ -1,79 +0,0 @@
const addBrunoRequestShimToContext = (context, req) => {
context.global.setSync('getUrl', function () {
return req.getUrl();
});
context.global.setSync('setUrl', function (url) {
req.setUrl(url);
});
context.global.setSync('getMethod', function () {
return req.getMethod();
});
context.global.setSync('getAuthMode', function () {
return req.getAuthMode();
});
context.global.setSync('setMethod', function (method) {
req.setMethod(method);
});
context.global.setSync('getHeaders', function () {
return req.getHeaders();
});
context.global.setSync('setHeaders', function (headers) {
req.setHeaders(headers);
});
context.global.setSync('getHeader', function (name) {
return req.getHeader(name);
});
context.global.setSync('setHeader', function (name, value) {
req.setHeader(name, value);
});
context.global.setSync('getBody', function () {
return req.getBody();
});
context.global.setSync('setBody', function (data) {
req.setBody(data);
});
context.global.setSync('setMaxRedirects', function (maxRedirects) {
req.setMaxRedirects(maxRedirects);
});
context.global.setSync('getTimeout', function () {
return req.getTimeout();
});
context.global.setSync('setTimeout', function (timeout) {
req.setTimeout(timeout);
});
context.evalSync(`
req = {
...req || {},
getUrl: global.getUrl,
setUrl: global.setUrl,
getMethod: global.getMethod,
getAuthMode: global.getAuthMode,
setMethod: global.setMethod,
getHeaders: global.getHeaders,
setHeaders: global.setHeaders,
getHeader: global.getHeader,
setHeader: global.setHeader,
getBody: global.getBody,
setBody: global.setBody,
setMaxRedirects: global.setMaxRedirects,
getTimeout: global.getTimeout,
setTimeout: global.setTimeout
}
`);
};
module.exports = addBrunoRequestShimToContext;

View File

@@ -1,46 +0,0 @@
const ivm = require('isolated-vm');
const addBrunoResponseShimToContext = (context, res) => {
context.global.setSync('status', new ivm.ExternalCopy(res?.status).copyInto());
context.global.setSync('headers', new ivm.ExternalCopy(res?.headers).copyInto());
context.global.setSync('body', new ivm.ExternalCopy(res?.body).copyInto());
context.global.setSync('responseTime', new ivm.ExternalCopy(res?.responseTime).copyInto());
context.global.setSync('getStatus', function () {
return res?.getStatus();
});
context.global.setSync('getHeader', function (name) {
return res?.getHeader(name);
});
context.global.setSync('getHeaders', function () {
return res?.getHeaders();
});
context.global.setSync('getBody', function () {
return res?.getBody();
});
context.global.setSync('getResponseTime', function () {
return res?.getResponseTime();
});
context.evalSync(`
res = {
...res || {},
status: global.status,
statusText: global.statusText,
headers: global.headers,
body: global.body,
responseTime: global.responseTime,
getStatus: global.getStatus,
getHeader: global.getHeader,
getHeaders: global.getHeaders,
getBody: global.getBody,
getResponseTime: global.getResponseTime
}
`);
};
module.exports = addBrunoResponseShimToContext;

View File

@@ -1,39 +0,0 @@
const addConsoleShimToContext = (context, console) => {
context.global.setSync('log', function (...args) {
console?.log && console.log(...args);
return args;
});
context.global.setSync('debug', function (...args) {
console?.debug && console.debug(...args);
return args;
});
context.global.setSync('info', function (...args) {
console?.info && console.info(...args);
return args;
});
context.global.setSync('warn', function (...args) {
console?.warn && console.warn(...args);
return args;
});
context.global.setSync('error', function (...args) {
console?.error && console.error(...args);
return args;
});
context.evalSync(`
console = {
...console || {},
log: global.log,
debug: global.debug,
info: global.info,
warn: global.warn,
error: global.error
}
`);
};
module.exports = addConsoleShimToContext;

View File

@@ -1,57 +0,0 @@
const axios = require('axios');
const ivm = require('isolated-vm');
const { cleanJson } = require('../../../../utils');
const addAxiosShimToContext = async (context) => {
await context.evalClosure(
`
globalThis.axios = (...args) => $0.applySyncPromise(undefined, args?.map(arg=>JSON.stringify(arg)));
${['get', 'post', 'put', 'patch', 'delete']
?.map(
(method, idx) =>
`globalThis.axios.${method} = (...args) => $${
idx + 1
}.applySyncPromise(undefined, args?.map(arg=>JSON.stringify(arg)))`
)
.join('\n')}
globalThis.requireObject = {
...globalThis.requireObject,
axios: globalThis.axios,
}
`,
[
async (...argStrings) => {
console.log(argStrings);
let args = argStrings?.map((arg) => JSON.parse(arg));
const res = await axios(...args)
.then((response) => {
return cleanJson(response?.data);
})
.catch((err) => {
return {
message: err.message
// response: cleanJson(err.response)
};
});
return new ivm.ExternalCopy(res).copyInto({ release: true });
},
...['get', 'post', 'put', 'patch', 'delete']?.map((method) => async (...argStrings) => {
let args = argStrings?.map((arg) => JSON.parse(arg));
const res = await axios[method](...args)
.then((response) => {
return cleanJson(response?.data);
})
.catch((err) => {
return {
message: err.message
// response: cleanJson(err.response)
};
});
return new ivm.ExternalCopy(res).copyInto({ release: true });
})
],
{ arguments: { reference: true } }
);
};
module.exports = addAxiosShimToContext;

View File

@@ -1,121 +0,0 @@
const axios = require('axios');
const ivm = require('isolated-vm');
const { cleanJson } = require('../../../../utils');
const addAxiosShimToContext = async (context) => {
await context.evalClosure(
`
globalThis.axios = (...args) => $0.applySyncPromise(undefined, args?.map(arg=>JSON.stringify(arg)));
globalThis.axios.get = (...args) => $1.applySyncPromise(undefined, args?.map(arg=>JSON.stringify(arg)));
globalThis.axios.post = (...args) => $2.applySyncPromise(undefined, args?.map(arg=>JSON.stringify(arg)));
globalThis.axios.put = (...args) => $3.applySyncPromise(undefined, args?.map(arg=>JSON.stringify(arg)));
globalThis.axios.delete = (...args) => $4.applySyncPromise(undefined, args?.map(arg=>JSON.stringify(arg)));
globalThis.axios.patch = (...args) => $5.applySyncPromise(undefined, args?.map(arg=>JSON.stringify(arg)));
globalThis.requireObject = {
...globalThis.requireObject,
axios: globalThis.axios,
}
`,
[
async (...argStrings) => {
console.log(argStrings);
let args = argStrings?.map((arg) => JSON.parse(arg));
const res = await axios(...args)
.then((response) => {
const { status, headers, data } = response || {};
return cleanJson({ status, headers, data });
})
.catch((err) => {
return {
message: err.message
// response: cleanJson(err.response)
};
});
return new ivm.ExternalCopy(res).copyInto({ release: true });
},
async (...argStrings) => {
let args = argStrings?.map((arg) => JSON.parse(arg));
const res = await axios
.get(...args)
.then((response) => {
const { status, headers, data } = response || {};
return cleanJson({ status, headers, data });
})
.catch((err) => {
return {
message: err.message
// response: cleanJson(err.response)
};
});
return new ivm.ExternalCopy(res).copyInto({ release: true });
},
async (...argStrings) => {
let args = argStrings?.map((arg) => JSON.parse(arg));
const res = await axios
.post(...args)
.then((response) => {
const { status, headers, data } = response || {};
return cleanJson({ status, headers, data });
})
.catch((err) => {
return {
message: err.message
// response: cleanJson(err.response)
};
});
return new ivm.ExternalCopy(res).copyInto({ release: true });
},
async (...argStrings) => {
let args = argStrings?.map((arg) => JSON.parse(arg));
const res = await axios
.put(...args)
.then((response) => {
const { status, headers, data } = response || {};
return cleanJson({ status, headers, data });
})
.catch((err) => {
return {
message: err.message
// response: cleanJson(err.response)
};
});
return new ivm.ExternalCopy(res).copyInto({ release: true });
},
async (...argStrings) => {
let args = argStrings?.map((arg) => JSON.parse(arg));
const res = await axios
.delete(...args)
.then((response) => {
const { status, headers, data } = response || {};
return cleanJson({ status, headers, data });
})
.catch((err) => {
return {
message: err.message
// response: cleanJson(err.response)
};
});
return new ivm.ExternalCopy(res).copyInto({ release: true });
},
async (...argStrings) => {
let args = argStrings?.map((arg) => JSON.parse(arg));
const res = await axios
.patch(...args)
.then((response) => {
const { status, headers, data } = response || {};
return cleanJson({ status, headers, data });
})
.catch((err) => {
return {
message: err.message
// response: cleanJson(err.response)
};
});
return new ivm.ExternalCopy(res).copyInto({ release: true });
}
],
{ arguments: { reference: true } }
);
};
module.exports = addAxiosShimToContext;

View File

@@ -1,11 +0,0 @@
const addAxiosShimToContext = require('./axios');
const addNanoidShimToContext = require('./nanoid');
const addUuidShimToContext = require('./uuid');
const addLibraryShimsToContext = async (context) => {
await addAxiosShimToContext(context);
await addNanoidShimToContext(context);
await addUuidShimToContext(context);
};
module.exports = addLibraryShimsToContext;

View File

@@ -1,23 +0,0 @@
const ivm = require('isolated-vm');
const { nanoid } = require('nanoid');
const addNanoidShimToContext = async (context) => {
await context.evalClosure(
`
globalThis.nanoid = {};
globalThis.nanoid.nanoid = () => $0.applySync(undefined);
globalThis.requireObject = {
...globalThis.requireObject,
nanoid: globalThis.nanoid
}
`,
[
() => {
return new ivm.ExternalCopy(nanoid()).copyInto({ release: true });
}
],
{ arguments: { reference: true } }
);
};
module.exports = addNanoidShimToContext;

View File

@@ -1,39 +0,0 @@
const ivm = require('isolated-vm');
const uuid = require('uuid');
const { MAX, NIL } = uuid;
const addUuidShimToContext = async (context) => {
await context.evalClosure(
`
globalThis.uuid = {};
globalThis.uuid.MAX = $0;
globalThis.uuid.NIL = $1;
${['version', 'parse', 'stringify', 'v1', 'v1ToV6', 'v3', 'v4', 'v5', 'v6', 'v6ToV1', 'v7', 'validate']
?.map(
(fn, idx) =>
`globalThis.uuid.${fn} = (...args) => $${
idx + 2
}.applySync(undefined, args?.map(arg=>JSON.stringify(arg)));`
)
.join('\n')}
globalThis.requireObject = {
...globalThis.requireObject,
uuid: globalThis.uuid,
}
`,
[
new ivm.ExternalCopy(MAX).copyInto({ release: true }),
new ivm.ExternalCopy(NIL).copyInto({ release: true }),
...['version', 'parse', 'stringify', 'v1', 'v1ToV6', 'v3', 'v4', 'v5', 'v6', 'v6ToV1', 'v7', 'validate']?.map(
(fn) =>
(...argStrings) => {
let args = argStrings?.map((arg) => JSON.parse(arg));
return new ivm.ExternalCopy(uuid[fn](...args)).copyInto({ release: true });
}
)
],
{ arguments: { reference: true } }
);
};
module.exports = addUuidShimToContext;

View File

@@ -1,83 +0,0 @@
const ivm = require('isolated-vm');
const { MAX, NIL, parse, stringify, v1, v1ToV6, v3, v4, v5, v6, v6ToV1, v7, validate, version } = require('uuid');
const addUuidShimToContext = async (context) => {
await context.evalClosure(
`
globalThis.uuid = {};
globalThis.uuid.MAX = $0;
globalThis.uuid.NIL = $1;
globalThis.uuid.version = (...args) => $2.applySync(undefined, args?.map(arg=>JSON.stringify(arg)));
globalThis.uuid.parse = (...args) => $3.applySync(undefined, args?.map(arg=>JSON.stringify(arg)));
globalThis.uuid.stringify = (...args) => $4.applySync(undefined, args?.map(arg=>JSON.stringify(arg)));
globalThis.uuid.v1 = (...args) => $5.applySync(undefined, args?.map(arg=>JSON.stringify(arg)));
globalThis.uuid.v1ToV6 = (...args) => $6.applySync(undefined, args?.map(arg=>JSON.stringify(arg)));
globalThis.uuid.v3 = (...args) => $7.applySync(undefined, args?.map(arg=>JSON.stringify(arg)));
globalThis.uuid.v4 = (...args) => $8.applySync(undefined, args?.map(arg=>JSON.stringify(arg)));
globalThis.uuid.v5 = (...args) => $9.applySync(undefined, args?.map(arg=>JSON.stringify(arg)));
globalThis.uuid.v6 = (...args) => $10.applySync(undefined, args?.map(arg=>JSON.stringify(arg)));
globalThis.uuid.v6ToV1 = (...args) => $11.applySync(undefined, args?.map(arg=>JSON.stringify(arg)));
globalThis.uuid.v7 = (...args) => $12.applySync(undefined, args?.map(arg=>JSON.stringify(arg)));
globalThis.uuid.validate = (...args) => $13.applySync(undefined, args?.map(arg=>JSON.stringify(arg)));
globalThis.requireObject = {
...globalThis.requireObject,
uuid: globalThis.uuid,
}
`,
[
new ivm.ExternalCopy(MAX).copyInto({ release: true }),
new ivm.ExternalCopy(NIL).copyInto({ release: true }),
(...argStrings) => {
let args = argStrings?.map((arg) => JSON.parse(arg));
return new ivm.ExternalCopy(version(...args)).copyInto({ release: true });
},
(...argStrings) => {
let args = argStrings?.map((arg) => JSON.parse(arg));
return new ivm.ExternalCopy(parse(...args)).copyInto({ release: true });
},
(...argStrings) => {
let args = argStrings?.map((arg) => JSON.parse(arg));
return new ivm.ExternalCopy(stringify(...args)).copyInto({ release: true });
},
(...argStrings) => {
let args = argStrings?.map((arg) => JSON.parse(arg));
return new ivm.ExternalCopy(v1(...args)).copyInto({ release: true });
},
(...argStrings) => {
let args = argStrings?.map((arg) => JSON.parse(arg));
return new ivm.ExternalCopy(v1ToV6(...args)).copyInto({ release: true });
},
(...argStrings) => {
let args = argStrings?.map((arg) => JSON.parse(arg));
return new ivm.ExternalCopy(v3(...args)).copyInto({ release: true });
},
(...argStrings) => {
let args = argStrings?.map((arg) => JSON.parse(arg));
return new ivm.ExternalCopy(v4(...args)).copyInto({ release: true });
},
(...argStrings) => {
let args = argStrings?.map((arg) => JSON.parse(arg));
return new ivm.ExternalCopy(v5(...args)).copyInto({ release: true });
},
(...argStrings) => {
let args = argStrings?.map((arg) => JSON.parse(arg));
return new ivm.ExternalCopy(v6(...args)).copyInto({ release: true });
},
(...argStrings) => {
let args = argStrings?.map((arg) => JSON.parse(arg));
return new ivm.ExternalCopy(v6ToV1(...args)).copyInto({ release: true });
},
(...argStrings) => {
let args = argStrings?.map((arg) => JSON.parse(arg));
return new ivm.ExternalCopy(v7(...args)).copyInto({ release: true });
},
(...argStrings) => {
let args = argStrings?.map((arg) => JSON.parse(arg));
return new ivm.ExternalCopy(validate(...args)).copyInto({ release: true });
}
],
{ arguments: { reference: true } }
);
};
module.exports = addUuidShimToContext;

View File

@@ -1,32 +0,0 @@
const ivm = require('isolated-vm');
const addSleepShimToContext = (context, console) => {
context.evalClosureSync(
`
global.sleep = (...args) => $0.applySyncPromise(undefined, args?.map(arg=>JSON.stringify(arg)));
`,
[
async (...argStrings) => {
await new Promise((resolve) => {
const timer = Number(argStrings?.[0]);
if (!Number.isInteger(timer) || timer < 0) {
resolve();
}
setTimeout(() => {
resolve();
}, timer);
});
return new ivm.ExternalCopy('done').copyInto({ release: true });
}
],
{ arguments: { reference: true } }
);
context.evalSync(`
global.setTimeout = async (fn, timer) => {
await sleep(timer);
await fn.apply();
}
`);
};
module.exports = addSleepShimToContext;

View File

@@ -1,56 +0,0 @@
const addTestShimToContext = async (context, __brunoTestResults) => {
context.global.setSync('addResult', function (v) {
__brunoTestResults.addResult(v);
});
context.global.setSync('getResults', function () {
return __brunoTestResults.getResults();
});
context.evalSync(`
globalThis.expect = require('chai').expect;
globalThis.assert = require('chai').assert;
globalThis.__brunoTestResults = {
addResult: globalThis.__bruno__addResult,
getResults: globalThis.__bruno__getResults,
}
globalThis.DummyChaiAssertionError = class DummyChaiAssertionError extends Error {
constructor(message, props, ssf) {
super(message);
this.name = "AssertionError";
Object.assign(this, props);
}
}
globalThis.Test = (__brunoTestResults) => async (description, callback) => {
try {
await callback();
__brunoTestResults.addResult({ description, status: "pass" });
} catch (error) {
if (error instanceof DummyChaiAssertionError) {
const { message, actual, expected } = error;
__brunoTestResults.addResult({
description,
status: "fail",
error: message,
actual,
expected,
});
} else {
globalThis.__bruno__addResult({
description,
status: "fail",
error: error.message || "An unexpected error occurred.",
});
}
// console.log(error);
}
};
globalThis.test = Test(__brunoTestResults);
`);
};
module.exports = addTestShimToContext;

View File

@@ -6,7 +6,7 @@ const addTestShimToContext = require('./shims/test');
const addLibraryShimsToContext = require('./shims/lib');
const { newQuickJSWASMModule, memoizePromiseFactory } = require('quickjs-emscripten');
// execute `npm run build:isolated-vm:inbuilt-modules` if the below file doesn't exist
// execute `npm run sandbox:bundle-libraries` if the below file doesn't exist
const getBundledCode = require('../../bundle-browser-rollup');
const addSleepShimToContext = require('./shims/sleep');
@@ -20,7 +20,7 @@ const toNumber = (value) => {
return Number.isInteger(num) ? parseInt(value, 10) : parseFloat(value);
};
const executeQuickJsVm = ({ script: externalScript, context: externalContext, scriptType = 'script' }) => {
const executeQuickJsVm = ({ script: externalScript, context: externalContext, scriptType = 'template-literal' }) => {
if (!isNaN(Number(externalScript))) {
return Number(externalScript);
}
@@ -35,7 +35,6 @@ const executeQuickJsVm = ({ script: externalScript, context: externalContext, sc
res && addBrunoResponseShimToContext(vm, res);
const templateLiteralText = `\`${externalScript}\`;`;
const jsExpressionText = `${externalScript};`;
let scriptText = scriptType === 'template-literal' ? templateLiteralText : jsExpressionText;
@@ -54,14 +53,11 @@ const executeQuickJsVm = ({ script: externalScript, context: externalContext, sc
} catch (error) {
console.error('Error executing the script!', error);
}
// });
};
const executeQuickJsVmAsync = async ({
script: externalScript,
context: externalContext,
modules = {},
scriptType = 'script'
context: externalContext
}) => {
if (!isNaN(Number(externalScript))) {
return toNumber(externalScript);
@@ -100,14 +96,12 @@ const executeQuickJsVmAsync = async ({
fn.apply();
}
await sleep(0);
console?.debug && console.debug('quick-js:execution-start:');
try {
${externalScript}
}
catch(error) {
console?.debug && console.debug('quick-js:execution-end:with-error', error?.message);
}
console?.debug && console.debug('quick-js:execution-end:');
return 'done';
})()
`;
@@ -119,7 +113,7 @@ const executeQuickJsVmAsync = async ({
const resolvedHandle = vm.unwrapResult(resolvedResult);
resolvedHandle.dispose();
// vm.dispose();
return 'foo';
return;
} catch (error) {
console.error('Error executing the script!', error);
}

View File

@@ -25,7 +25,7 @@ script:pre-request {
const math = require("./lib/math");
const body = req.getBody();
body.sum = body.a + body.b;
body.sum = math.sum(body.a, body.b);
req.setBody(body);
}