mirror of
https://github.com/usebruno/bruno.git
synced 2025-02-16 17:51:48 +01:00
feat: safe mode quickjs updates (#2866)
* wip: safe mode updates * wip: safe mode quickjs updates * wip: safe mode updates * wip: safe mode updates * wip: safe mode updates
This commit is contained in:
parent
35376305ae
commit
64cb45c09a
8
package-lock.json
generated
8
package-lock.json
generated
@ -8340,6 +8340,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
|
||||||
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
|
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
|
||||||
},
|
},
|
||||||
|
"node_modules/crypto-js-3.1.9-1": {
|
||||||
|
"name": "crypto-js",
|
||||||
|
"version": "3.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.3.0.tgz",
|
||||||
|
"integrity": "sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q=="
|
||||||
|
},
|
||||||
"node_modules/crypto-random-string": {
|
"node_modules/crypto-random-string": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
|
||||||
@ -20595,12 +20601,14 @@
|
|||||||
"chai": "^4.3.7",
|
"chai": "^4.3.7",
|
||||||
"chai-string": "^1.5.0",
|
"chai-string": "^1.5.0",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
|
"crypto-js-3.1.9-1": "npm:crypto-js@^3.1.9-1",
|
||||||
"json-query": "^2.2.2",
|
"json-query": "^2.2.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"nanoid": "3.3.4",
|
"nanoid": "3.3.4",
|
||||||
"node-fetch": "^2.7.0",
|
"node-fetch": "^2.7.0",
|
||||||
"node-vault": "^0.10.2",
|
"node-vault": "^0.10.2",
|
||||||
|
"path": "^0.12.7",
|
||||||
"quickjs-emscripten": "^0.29.2",
|
"quickjs-emscripten": "^0.29.2",
|
||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0"
|
||||||
},
|
},
|
||||||
|
@ -25,12 +25,14 @@
|
|||||||
"chai": "^4.3.7",
|
"chai": "^4.3.7",
|
||||||
"chai-string": "^1.5.0",
|
"chai-string": "^1.5.0",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
|
"crypto-js-3.1.9-1": "npm:crypto-js@^3.1.9-1",
|
||||||
"json-query": "^2.2.2",
|
"json-query": "^2.2.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"nanoid": "3.3.4",
|
"nanoid": "3.3.4",
|
||||||
"node-fetch": "^2.7.0",
|
"node-fetch": "^2.7.0",
|
||||||
"node-vault": "^0.10.2",
|
"node-vault": "^0.10.2",
|
||||||
|
"path": "^0.12.7",
|
||||||
"quickjs-emscripten": "^0.29.2",
|
"quickjs-emscripten": "^0.29.2",
|
||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0"
|
||||||
},
|
},
|
||||||
|
@ -84,6 +84,9 @@ class TestRuntime {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add 'await' prefix to the test function calls
|
||||||
|
testsFile = testsFile.replace(/^(?!\s*await\s)(test\([^)]*\))/gm, 'await $1');
|
||||||
|
|
||||||
const context = {
|
const context = {
|
||||||
test,
|
test,
|
||||||
bru,
|
bru,
|
||||||
|
@ -11,18 +11,22 @@ const bundleLibraries = async () => {
|
|||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import btoa from "btoa";
|
import btoa from "btoa";
|
||||||
import atob from "atob";
|
import atob from "atob";
|
||||||
|
import * as CryptoJS from "crypto-js-3.1.9-1";
|
||||||
globalThis.expect = expect;
|
globalThis.expect = expect;
|
||||||
globalThis.assert = assert;
|
globalThis.assert = assert;
|
||||||
globalThis.moment = moment;
|
globalThis.moment = moment;
|
||||||
globalThis.btoa = btoa;
|
globalThis.btoa = btoa;
|
||||||
globalThis.atob = atob;
|
globalThis.atob = atob;
|
||||||
globalThis.Buffer = Buffer;
|
globalThis.Buffer = Buffer;
|
||||||
|
globalThis.CryptoJS = CryptoJS;
|
||||||
globalThis.requireObject = {
|
globalThis.requireObject = {
|
||||||
|
...(globalThis.requireObject || {}),
|
||||||
'chai': { expect, assert },
|
'chai': { expect, assert },
|
||||||
'moment': moment,
|
'moment': moment,
|
||||||
'buffer': { Buffer },
|
'buffer': { Buffer },
|
||||||
'btoa': btoa,
|
'btoa': btoa,
|
||||||
'atob': atob,
|
'atob': atob,
|
||||||
|
'crypto-js': CryptoJS
|
||||||
};
|
};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ const { newQuickJSWASMModule, memoizePromiseFactory } = require('quickjs-emscrip
|
|||||||
|
|
||||||
// execute `npm run sandbox:bundle-libraries` 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 getBundledCode = require('../bundle-browser-rollup');
|
||||||
|
const addPathShimToContext = require('./shims/lib/path');
|
||||||
|
|
||||||
let QuickJSSyncContext;
|
let QuickJSSyncContext;
|
||||||
const loader = memoizePromiseFactory(() => newQuickJSWASMModule());
|
const loader = memoizePromiseFactory(() => newQuickJSWASMModule());
|
||||||
@ -64,14 +65,14 @@ const executeQuickJsVmAsync = async ({ script: externalScript, context: external
|
|||||||
const vm = module.newContext();
|
const vm = module.newContext();
|
||||||
|
|
||||||
const bundledCode = getBundledCode?.toString() || '';
|
const bundledCode = getBundledCode?.toString() || '';
|
||||||
const moduleLoaderCode = function() {
|
const moduleLoaderCode = function () {
|
||||||
return `
|
return `
|
||||||
globalThis.require = (mod) => {
|
globalThis.require = (mod) => {
|
||||||
let lib = globalThis.requireObject[mod];
|
let lib = globalThis.requireObject[mod];
|
||||||
if (lib) {
|
if (lib) {
|
||||||
return lib;
|
return lib;
|
||||||
}
|
}
|
||||||
else {
|
else if(mod?.startsWith('.') || mod?.startsWith?.(bru.cwd())){
|
||||||
// fetch local module
|
// fetch local module
|
||||||
let localModuleCode = globalThis.__brunoLoadLocalModule(mod);
|
let localModuleCode = globalThis.__brunoLoadLocalModule(mod);
|
||||||
|
|
||||||
@ -79,7 +80,12 @@ const executeQuickJsVmAsync = async ({ script: externalScript, context: external
|
|||||||
(function (){
|
(function (){
|
||||||
const initModuleExportsCode = "const module = { exports: {} };"
|
const initModuleExportsCode = "const module = { exports: {} };"
|
||||||
const copyModuleExportsCode = "\\n;globalThis.requireObject[mod] = module.exports;";
|
const copyModuleExportsCode = "\\n;globalThis.requireObject[mod] = module.exports;";
|
||||||
eval(initModuleExportsCode + localModuleCode + copyModuleExportsCode);
|
const patchedRequire = ${`
|
||||||
|
"\\n;" +
|
||||||
|
"let require = (subModule) => globalThis.require(path.resolve(bru.cwd(), mod, '..', subModule))" +
|
||||||
|
"\\n;"
|
||||||
|
`}
|
||||||
|
eval(initModuleExportsCode + patchedRequire + localModuleCode + copyModuleExportsCode);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// resolve module
|
// resolve module
|
||||||
@ -103,6 +109,7 @@ const executeQuickJsVmAsync = async ({ script: externalScript, context: external
|
|||||||
res && addBrunoResponseShimToContext(vm, res);
|
res && addBrunoResponseShimToContext(vm, res);
|
||||||
consoleFn && addConsoleShimToContext(vm, consoleFn);
|
consoleFn && addConsoleShimToContext(vm, consoleFn);
|
||||||
addLocalModuleLoaderShimToContext(vm, collectionPath);
|
addLocalModuleLoaderShimToContext(vm, collectionPath);
|
||||||
|
addPathShimToContext(vm);
|
||||||
|
|
||||||
await addLibraryShimsToContext(vm);
|
await addLibraryShimsToContext(vm);
|
||||||
|
|
||||||
@ -135,6 +142,7 @@ const executeQuickJsVmAsync = async ({ script: externalScript, context: external
|
|||||||
return;
|
return;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error executing the script!', error);
|
console.error('Error executing the script!', error);
|
||||||
|
throw new Error(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
const addAxiosShimToContext = require('./axios');
|
const addAxiosShimToContext = require('./axios');
|
||||||
const addNanoidShimToContext = require('./nanoid');
|
const addNanoidShimToContext = require('./nanoid');
|
||||||
const addNodeFetchShimToContext = require('./node-fetch');
|
const addPathShimToContext = require('./path');
|
||||||
const addUuidShimToContext = require('./uuid');
|
const addUuidShimToContext = require('./uuid');
|
||||||
|
|
||||||
const addLibraryShimsToContext = async (vm) => {
|
const addLibraryShimsToContext = async (vm) => {
|
||||||
await addNanoidShimToContext(vm);
|
await addNanoidShimToContext(vm);
|
||||||
await addAxiosShimToContext(vm);
|
await addAxiosShimToContext(vm);
|
||||||
await addNodeFetchShimToContext(vm);
|
|
||||||
await addUuidShimToContext(vm);
|
await addUuidShimToContext(vm);
|
||||||
|
await addPathShimToContext(vm);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = addLibraryShimsToContext;
|
module.exports = addLibraryShimsToContext;
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
const fetch = require('node-fetch');
|
|
||||||
const { cleanJson } = require('../../../../utils');
|
|
||||||
const { marshallToVm } = require('../../utils');
|
|
||||||
|
|
||||||
const addNodeFetchShimToContext = async (vm) => {
|
|
||||||
const nodeFetchHandle = vm.newFunction('node_fetch', (...args) => {
|
|
||||||
const nativeArgs = args.map(vm.dump);
|
|
||||||
const promise = vm.newPromise();
|
|
||||||
fetch(...nativeArgs)
|
|
||||||
.then(async (response) => {
|
|
||||||
const { status, headers } = response || {};
|
|
||||||
const data = await response.json();
|
|
||||||
promise.resolve(marshallToVm(cleanJson({ status, headers, data }), vm));
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
promise.resolve(
|
|
||||||
marshallToVm(
|
|
||||||
cleanJson({
|
|
||||||
message: err.message
|
|
||||||
}),
|
|
||||||
vm
|
|
||||||
)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
promise.settled.then(vm.runtime.executePendingJobs);
|
|
||||||
return promise.handle;
|
|
||||||
});
|
|
||||||
|
|
||||||
nodeFetchHandle.consume((handle) => vm.setProp(vm.global, `__bruno__node_fetch`, handle));
|
|
||||||
vm.evalCode(
|
|
||||||
`
|
|
||||||
globalThis.nodeFetch = __bruno__node_fetch;
|
|
||||||
globalThis.requireObject = {
|
|
||||||
...globalThis.requireObject,
|
|
||||||
'node-fetch': globalThis.nodeFetch,
|
|
||||||
}
|
|
||||||
`
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = addNodeFetchShimToContext;
|
|
28
packages/bruno-js/src/sandbox/quickjs/shims/lib/path.js
Normal file
28
packages/bruno-js/src/sandbox/quickjs/shims/lib/path.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
const path = require('path');
|
||||||
|
const { marshallToVm } = require('../../utils');
|
||||||
|
|
||||||
|
const fns = ['resolve'];
|
||||||
|
|
||||||
|
const addPathShimToContext = async (vm) => {
|
||||||
|
fns.forEach((fn) => {
|
||||||
|
let fnHandle = vm.newFunction(fn, function (...args) {
|
||||||
|
const nativeArgs = args.map(vm.dump);
|
||||||
|
return marshallToVm(path[fn](...nativeArgs), vm);
|
||||||
|
});
|
||||||
|
vm.setProp(vm.global, `__bruno__path__${fn}`, fnHandle);
|
||||||
|
fnHandle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
vm.evalCode(
|
||||||
|
`
|
||||||
|
globalThis.path = {};
|
||||||
|
${fns?.map((fn, idx) => `globalThis.path.${fn} = __bruno__path__${fn}`).join('\n')}
|
||||||
|
globalThis.requireObject = {
|
||||||
|
...(globalThis.requireObject || {}),
|
||||||
|
path: globalThis.path,
|
||||||
|
}
|
||||||
|
`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = addPathShimToContext;
|
@ -1,4 +1,4 @@
|
|||||||
const { PI } = require('./lib/constants');
|
const { PI } = require('./constants');
|
||||||
|
|
||||||
const sum = (a, b) => a + b;
|
const sum = (a, b) => a + b;
|
||||||
const areaOfCircle = (radius) => PI * radius * radius;
|
const areaOfCircle = (radius) => PI * radius * radius;
|
||||||
@ -6,4 +6,4 @@ const areaOfCircle = (radius) => PI * radius * radius;
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
sum,
|
sum,
|
||||||
areaOfCircle
|
areaOfCircle
|
||||||
};
|
};
|
||||||
|
@ -9,8 +9,3 @@ get {
|
|||||||
body: none
|
body: none
|
||||||
auth: none
|
auth: none
|
||||||
}
|
}
|
||||||
|
|
||||||
script:pre-request {
|
|
||||||
var CryptoJS = require("crypto-js");
|
|
||||||
console.log(CryptoJS);
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
meta {
|
||||||
|
name: crypto-js-pre-request-script
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{host}}/ping
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
|
|
||||||
|
script:pre-request {
|
||||||
|
var CryptoJS = require("crypto-js");
|
||||||
|
|
||||||
|
// Encrypt
|
||||||
|
var ciphertext = CryptoJS.AES.encrypt('my message', 'secret key 123').toString();
|
||||||
|
|
||||||
|
// Decrypt
|
||||||
|
var bytes = CryptoJS.AES.decrypt(ciphertext, 'secret key 123');
|
||||||
|
var originalText = bytes.toString(CryptoJS.enc.Utf8);
|
||||||
|
|
||||||
|
bru.setVar('crypto-test-message', originalText);
|
||||||
|
}
|
||||||
|
|
||||||
|
tests {
|
||||||
|
test("crypto message", function() {
|
||||||
|
const data = bru.getVar('crypto-test-message');
|
||||||
|
bru.setVar('crypto-test-message', null);
|
||||||
|
expect(data).to.eql('my message');
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
@ -13,5 +13,14 @@ get {
|
|||||||
script:pre-request {
|
script:pre-request {
|
||||||
const { nanoid } = require("nanoid");
|
const { nanoid } = require("nanoid");
|
||||||
|
|
||||||
req.setHeader("transaction-id", nanoid());
|
bru.setVar("nanoid-test-id", nanoid());
|
||||||
|
}
|
||||||
|
|
||||||
|
tests {
|
||||||
|
test("nanoid var", function() {
|
||||||
|
const id = bru.getVar('nanoid-test-id');
|
||||||
|
let isValidNanoid = /^[a-zA-Z0-9_-]{21}$/.test(id)
|
||||||
|
bru.setVar('nanoid-test-id', null);
|
||||||
|
expect(isValidNanoid).to.eql(true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
meta {
|
|
||||||
name: node-fetch-pre-req-script
|
|
||||||
type: http
|
|
||||||
seq: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
get {
|
|
||||||
url: {{host}}/ping
|
|
||||||
body: none
|
|
||||||
auth: none
|
|
||||||
}
|
|
||||||
|
|
||||||
script:pre-request {
|
|
||||||
const fetch = require("node-fetch");
|
|
||||||
|
|
||||||
const url = "https://testbench-sanity.usebruno.com/api/echo/json";
|
|
||||||
const response = await fetch(url, {
|
|
||||||
method: 'post',
|
|
||||||
body: JSON.stringify({hello:'bruno'}),
|
|
||||||
headers: {'Content-Type': 'application/json'}
|
|
||||||
});
|
|
||||||
|
|
||||||
req.setBody(response.data);
|
|
||||||
req.setMethod("POST");
|
|
||||||
req.setUrl(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
tests {
|
|
||||||
test("req.getBody()", function() {
|
|
||||||
const data = res.getBody();
|
|
||||||
expect(data).to.eql({
|
|
||||||
"hello": "bruno"
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
@ -13,5 +13,14 @@ get {
|
|||||||
script:pre-request {
|
script:pre-request {
|
||||||
const { v4 } = require("uuid");
|
const { v4 } = require("uuid");
|
||||||
|
|
||||||
req.setHeader("transaction-id", v4());
|
bru.setVar("uuid-test-id", v4());
|
||||||
|
}
|
||||||
|
|
||||||
|
tests {
|
||||||
|
test("uuid var", function() {
|
||||||
|
const id = bru.getVar('uuid-test-id');
|
||||||
|
let isValidUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(id);
|
||||||
|
bru.setVar('uuid-test-id', null);
|
||||||
|
expect(isValidUuid).to.eql(true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user