added async await functionality for scripts, tests. sync execution of asserts using quick-js (#2846)

This commit is contained in:
lohit
2024-08-16 18:11:40 +05:30
committed by GitHub
parent 7182ef3479
commit a42689a717
16 changed files with 820 additions and 235 deletions

View File

@@ -42,7 +42,7 @@ const runSingleRequest = async function (
// todo: allow to override from cli args
// we will default to vm2 (developer-mode) for 1.x version for backward compatibility
// 2.x will default to isolated-vm (safe mode)
scriptingConfig.runtime = 'isolated-vm';
scriptingConfig.runtime = 'quickjs';
// make axios work in node using form data
// reference: https://github.com/axios/axios/issues/1006#issuecomment-320165427

File diff suppressed because one or more lines are too long

View File

@@ -5,7 +5,7 @@ const Bru = require('../bru');
const BrunoRequest = require('../bruno-request');
const { evaluateJsTemplateLiteral, evaluateJsExpression, createResponseParser } = require('../utils');
const { interpolateString } = require('../interpolate-string');
const { executeInIsolatedVMStrict } = require('../sandbox/isolatedvm');
const { executeQuickJsVm } = require('../sandbox/quickjs');
const { expect } = chai;
chai.use(require('chai-string'));
@@ -163,8 +163,8 @@ const isUnaryOperator = (operator) => {
};
const evaluateJsTemplateLiteralBasedOnRuntime = (literal, context, runtime) => {
if(runtime === 'isolated-vm') {
return executeInIsolatedVMStrict({
if (runtime === 'quickjs') {
return executeQuickJsVm({
script: literal,
context,
scriptType: 'template-literal'
@@ -175,8 +175,8 @@ const evaluateJsTemplateLiteralBasedOnRuntime = (literal, context, runtime) => {
};
const evaluateJsExpressionBasedOnRuntime = (expr, context, runtime) => {
if(runtime === 'isolated-vm') {
return executeInIsolatedVMStrict({
if (runtime === 'quickjs') {
return executeQuickJsVm({
script: expr,
context,
scriptType: 'expression'
@@ -184,7 +184,7 @@ const evaluateJsExpressionBasedOnRuntime = (expr, context, runtime) => {
}
return evaluateJsExpression(expr, context);
}
};
const evaluateRhsOperand = (rhsOperand, operator, context, runtime) => {
if (isUnaryOperator(operator)) {
@@ -207,11 +207,7 @@ const evaluateRhsOperand = (rhsOperand, operator, context, runtime) => {
return rhsOperand
.split(',')
.map((v) =>
evaluateJsTemplateLiteralBasedOnRuntime(
interpolateString(v.trim(), interpolationContext),
context,
runtime
)
evaluateJsTemplateLiteralBasedOnRuntime(interpolateString(v.trim(), interpolationContext), context, runtime)
);
}
@@ -219,11 +215,7 @@ const evaluateRhsOperand = (rhsOperand, operator, context, runtime) => {
const [lhs, rhs] = rhsOperand
.split(',')
.map((v) =>
evaluateJsTemplateLiteralBasedOnRuntime(
interpolateString(v.trim(), interpolationContext),
context,
runtime
)
evaluateJsTemplateLiteralBasedOnRuntime(interpolateString(v.trim(), interpolationContext), context, runtime)
);
return [lhs, rhs];
}
@@ -237,11 +229,7 @@ const evaluateRhsOperand = (rhsOperand, operator, context, runtime) => {
return interpolateString(rhsOperand, interpolationContext);
}
return evaluateJsTemplateLiteralBasedOnRuntime(
interpolateString(rhsOperand, interpolationContext),
context,
runtime
);
return evaluateJsTemplateLiteralBasedOnRuntime(interpolateString(rhsOperand, interpolationContext), context, runtime);
};
class AssertRuntime {

View File

@@ -28,7 +28,7 @@ const fetch = require('node-fetch');
const chai = require('chai');
const CryptoJS = require('crypto-js');
const NodeVault = require('node-vault');
const { executeInIsolatedVMAsync } = require('../sandbox/isolatedvm');
const { executeQuickJsVmAsync } = require('../sandbox/quickjs');
class ScriptRuntime {
constructor(props) {
@@ -89,22 +89,22 @@ class ScriptRuntime {
};
}
if (this.runtime === 'isolated-vm') {
await executeInIsolatedVMAsync({
if (this.runtime === 'quickjs') {
await executeQuickJsVmAsync({
script: script,
context: context,
modules: {},
scriptType: 'jsScript'
});
return {
request,
envVariables: cleanJson(envVariables),
runtimeVariables: cleanJson(runtimeVariables),
nextRequestName: bru.nextRequest
};
}
return {
request,
envVariables: cleanJson(envVariables),
runtimeVariables: cleanJson(runtimeVariables),
nextRequestName: bru.nextRequest
};
// default runtime is vm2
const vm = new NodeVM({
sandbox: context,
@@ -202,8 +202,8 @@ class ScriptRuntime {
};
}
if (this.runtime === 'isolated-vm') {
await executeInIsolatedVMAsync({
if (this.runtime === 'quickjs') {
await executeQuickJsVmAsync({
script: script,
context: context,
modules: {},

View File

@@ -30,7 +30,6 @@ const axios = require('axios');
const fetch = require('node-fetch');
const CryptoJS = require('crypto-js');
const NodeVault = require('node-vault');
const { executeInIsolatedVMAsync } = require('../sandbox/isolatedvm');
const { executeQuickJsVmAsync } = require('../sandbox/quickjs');
class TestRuntime {
@@ -109,18 +108,13 @@ class TestRuntime {
};
}
if (this.runtime === 'isolated-vm') {
await executeInIsolatedVMAsync({
if (this.runtime === 'quickjs') {
await executeQuickJsVmAsync({
script: testsFile,
context: context,
modules: {},
scriptType: 'jsScript'
});
} else if(this.runtime === 'quickjs') {
await executeQuickJsVmAsync({
script: testsFile,
context: context
});
} else {
// default runtime is vm2
const vm = new NodeVM({

View File

@@ -3,11 +3,11 @@ const Bru = require('../bru');
const BrunoRequest = require('../bruno-request');
const { evaluateJsTemplateLiteral, evaluateJsExpression, createResponseParser } = require('../utils');
const { executeInIsolatedVMStrict } = require('../sandbox/isolatedvm');
const { executeQuickJsVm } = require('../sandbox/quickjs');
const evaluateJsTemplateLiteralBasedOnRuntime = (literal, context, runtime) => {
if(runtime === 'isolated-vm') {
return executeInIsolatedVMStrict({
if (runtime === 'quickjs') {
return executeQuickJsVm({
script: literal,
context,
scriptType: 'template-literal'
@@ -18,8 +18,8 @@ const evaluateJsTemplateLiteralBasedOnRuntime = (literal, context, runtime) => {
};
const evaluateJsExpressionBasedOnRuntime = (expr, context, runtime, mode) => {
if(runtime === 'isolated-vm') {
return executeInIsolatedVMStrict({
if (runtime === 'quickjs') {
return executeQuickJsVm({
script: expr,
context,
scriptType: 'expression'

View File

@@ -8,16 +8,15 @@ const addTestShimToContext = async (context, __brunoTestResults) => {
});
context.evalSync(`
global.expect = require('chai').expect;
global.assert = require('chai').assert;
globalThis.expect = require('chai').expect;
globalThis.assert = require('chai').assert;
global.__brunoTestResults = {
addResult: global.addResult,
getResults: global.getResults,
globalThis.__brunoTestResults = {
addResult: globalThis.__bruno__addResult,
getResults: globalThis.__bruno__getResults,
}
global.DummyChaiAssertionError = class DummyChaiAssertionError extends Error {
globalThis.DummyChaiAssertionError = class DummyChaiAssertionError extends Error {
constructor(message, props, ssf) {
super(message);
this.name = "AssertionError";
@@ -25,7 +24,7 @@ const addTestShimToContext = async (context, __brunoTestResults) => {
}
}
global.Test = (__brunoTestResults) => async (description, callback) => {
globalThis.Test = (__brunoTestResults) => async (description, callback) => {
try {
await callback();
__brunoTestResults.addResult({ description, status: "pass" });
@@ -40,17 +39,17 @@ const addTestShimToContext = async (context, __brunoTestResults) => {
expected,
});
} else {
__brunoTestResults.addResult({
globalThis.__bruno__addResult({
description,
status: "fail",
error: error.message || "An unexpected error occurred.",
});
}
console.log(error);
// console.log(error);
}
};
global.test = Test(__brunoTestResults);
globalThis.test = Test(__brunoTestResults);
`);
};

View File

@@ -1,79 +1,89 @@
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 { newQuickJSAsyncWASMModule } = require('quickjs-emscripten');
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
const getBundledCode = require('../bundle-browser-rollup');
const getBundledCode = require('../../bundle-browser-rollup');
let QuickJSSyncContext;
const loader = memoizePromiseFactory(() => newQuickJSWASMModule());
const getContext = (opts) => loader().then((mod) => (QuickJSSyncContext = mod.newContext(opts)));
getContext();
const toNumber = (value) => {
const num = Number(value);
return Number.isInteger(num) ? parseInt(value, 10) : parseFloat(value);
};
const executeQuickJsVm = ({ script: externalScript, context: externalContext }) => {
const executeQuickJsVm = ({ 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 vm = QuickJSSyncContext;
try {
const { bru, req, res } = externalContext;
context.evalSync(`
let bru = {};
let req = {};
let res = {};
`);
bru && addBruShimToContext(vm, bru);
req && addBrunoRequestShimToContext(vm, req);
res && addBrunoResponseShimToContext(vm, res);
bru && addBruShimToContext(context, bru);
req && addBrunoRequestShimToContext(context, req);
res && addBrunoResponseShimToContext(context, res);
////////////////////////////////////////////////////////////////////////////////
context.global.setSync('setResult', function (arg) {
result = arg;
const logHandle = vm.newFunction('log', (...args) => {
const nativeArgs = args.map(vm.dump);
console.log(...nativeArgs);
});
vm.setProp(vm.global, 'log', logHandle);
logHandle.dispose();
const templateLiteralText = `
let value = \`${externalScript}\`;
setResult(value);
`;
////////////////////////////////////////////////////////////////////////////////
const jsExpressionText = `
let value = ${externalScript};
setResult(value);
`;
const templateLiteralText = `\`${externalScript}\`;`;
const jsExpressionText = `${externalScript};`;
let scriptText = scriptType === 'template-literal' ? templateLiteralText : jsExpressionText;
const script = isolate.compileScriptSync(scriptText);
script.runSync(context);
return result;
const result = vm.evalCode(scriptText);
if (result.error) {
let e = vm.dump(result.error);
result.error.dispose();
return e;
} else {
let v = vm.dump(result.value);
let vString = v.toString();
result.value.dispose();
return v;
}
} catch (error) {
console.error('Error executing the script!', error);
}
isolate.dispose();
// });
};
const executeQuickJsVmAsync = async ({
script: externalScript,
context: externalContext
context: externalContext,
modules = {},
scriptType = 'script'
}) => {
if (!isNaN(Number(externalScript))) {
return toNumber(externalScript);
}
try {
const module = await newQuickJSAsyncWASMModule()
const runtime = module.newRuntime()
const vm = runtime.newContext()
const module = await newQuickJSWASMModule();
const vm = module.newContext();
const bundledCode = getBundledCode?.toString() || '';
let bundledScript = `(${bundledCode})()`;
let bundledScript = `
(${bundledCode})()
`;
bundledScript += `
globalThis.require = (module) => {
@@ -81,117 +91,104 @@ const executeQuickJsVmAsync = async ({
}
`;
bundledScript += `
let bru = {
cwd: __bruno__cwd,
getEnvName: __bruno__getEnvName,
getProcessEnv: __bruno__getProcessEnv,
getEnvVar: __bruno__getEnvVar,
setEnvVar: __bruno__setEnvVar,
getVar: __bruno__getVar,
setVar: __bruno__setVar,
setNextRequest: __bruno__setNextRequest,
visualize: __bruno__visualize,
getSecretVar: __bruno__getSecretVar
};
let req = {
url: __bruno__req__url,
method: __bruno__req__method,
headers: __bruno__req__headers,
body: __bruno__req__body,
timeout: __bruno__req__timeout,
getUrl: __bruno__req__getUrl,
setUrl: __bruno__req__setUrl,
getMethod: __bruno__req__getMethod,
setMethod: __bruno__req__setMethod,
getAuthMode: __bruno__req__getAuthMode,
getHeaders: __bruno__req__getHeaders,
setHeaders: __bruno__req__setHeaders,
getHeader: __bruno__req__getHeader,
setHeader: __bruno__req__setHeader,
getBody: __bruno__req__getBody,
setBody: __bruno__req__setBody,
setMaxRedirects: __bruno__req__setMaxRedirects,
getTimeout: __bruno__req__getTimeout,
setTimeout: __bruno__req__setTimeout
};
let res = {
status: globalThis.__bruno__res__status,
headers: globalThis.__bruno__res__headers,
body: globalThis.__bruno__res__body,
responseTime: globalThis.__bruno__res__responseTime,
getStatus: globalThis.__bruno__res__getStatus,
getHeader: globalThis.__bruno__res__getHeader,
getHeaders: globalThis.__bruno__res__getHeaders,
getBody: globalThis.__bruno__res__getBody,
getResponseTime: globalThis.__bruno__res__getResponseTime
};
`;
const { bru, req, res, test, __brunoTestResults, console: consoleFn } = externalContext;
bru && addBruShimToContext(vm, bru);
req && addBrunoRequestShimToContext(vm, req);
res && addBrunoResponseShimToContext(vm, res);
consoleFn && addConsoleShimToContext(vm, consoleFn);
// await addLibraryShimsToContext(context);
test && __brunoTestResults && addTestShimToContext(vm, __brunoTestResults);
bundledScript += `
globalThis.expect = require('chai').expect;
globalThis.assert = require('chai').assert;
globalThis.expect = require('chai').expect;
globalThis.assert = require('chai').assert;
globalThis.__brunoTestResults = {
addResult: globalThis.__bruno__addResult,
getResults: globalThis.__bruno__getResults,
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.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.",
});
}
}
};
globalThis.Test = (__brunoTestResults) => (description, callback) => {
globalThis.test = Test(__brunoTestResults);
`;
////////////////////////////////////////////////////////////////////////////////
const sleep = vm.newFunction('sleep', (timer) => {
const t = vm.getString(timer);
const promise = vm.newPromise();
setTimeout(() => {
promise.resolve(vm.newString('slept'));
}, t);
promise.settled.then(vm.runtime.executePendingJobs);
return promise.handle;
});
sleep.consume((handle) => vm.setProp(vm.global, 'sleep', handle));
////////////////////////////////////////////////////////////////////////////////
const script = `
${bundledScript}
(async () => {
const setTimeout = async(fn, timer) => {
v = await sleep(timer);
fn.apply();
}
await sleep(0);
console?.debug && console.debug('quick-js:execution-start:');
try {
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 {
__brunoTestResults.addResult({
description,
status: "fail",
error: error.message || "An unexpected error occurred.",
});
}
// console.log(error);
${externalScript}
}
};
globalThis.test = Test(__brunoTestResults);
catch(error) {
console?.debug && console.debug('quick-js:execution-end:with-error', error?.message);
}
console?.debug && console.debug('quick-js:execution-end:');
return 'done';
})()
`;
bundledScript += externalScript;
const result = await vm.evalCodeAsync(bundledScript);
if (result.error) {
console.log("Execution failed:", vm.dump(result.error))
result.error.dispose()
} else {
result.value.dispose();
}
vm.dispose();
return result;
const result = vm.evalCode(script);
const promiseHandle = vm.unwrapResult(result);
const resolvedResult = await vm.resolvePromise(promiseHandle);
promiseHandle.dispose();
const resolvedHandle = vm.unwrapResult(resolvedResult);
resolvedHandle.dispose();
// vm.dispose();
return 'foo';
} catch (error) {
console.error('Error executing the script!', error);
}

View File

@@ -1,65 +1,70 @@
const { marshallToVm } = require('../utils');
const addBruShimToContext = (vm, bru) => {
const bruObject = vm.newObject();
let cwd = vm.newFunction('cwd', function () {
return marshallToVm(bru.cwd(), vm);
});
vm.setProp(vm.global, "__bruno__cwd", cwd)
vm.setProp(bruObject, 'cwd', cwd);
cwd.dispose();
let getEnvName = vm.newFunction('getEnvName', function () {
return marshallToVm(bru.getEnvName(), vm);
});
vm.setProp(vm.global, "__bruno__getEnvName", getEnvName);
vm.setProp(bruObject, 'getEnvName', getEnvName);
getEnvName.dispose();
let getProcessEnv = vm.newFunction('getProcessEnv', function (key) {
return marshallToVm(bru.getProcessEnv(vm.dump(key)), vm);
});
vm.setProp(vm.global, "__bruno__getProcessEnv", getProcessEnv);
vm.setProp(bruObject, 'getProcessEnv', getProcessEnv);
getProcessEnv.dispose();
let getEnvVar = vm.newFunction('getEnvVar', function (key) {
return marshallToVm(bru.getEnvVar(vm.dump(key)), vm);
});
vm.setProp(vm.global, "__bruno__getEnvVar", getEnvVar);
vm.setProp(bruObject, 'getEnvVar', getEnvVar);
getEnvVar.dispose();
let setEnvVar = vm.newFunction('setEnvVar', function (key, value) {
bru.setEnvVar(vm.dump(key), vm.dump(value));
});
vm.setProp(vm.global, "__bruno__setEnvVar", setEnvVar);
vm.setProp(bruObject, 'setEnvVar', setEnvVar);
setEnvVar.dispose();
let getVar = vm.newFunction('getVar', function (key) {
return marshallToVm(bru.getVar(vm.dump(key)), vm);
});
vm.setProp(vm.global, "__bruno__getVar", getVar);
vm.setProp(bruObject, 'getVar', getVar);
getVar.dispose();
let setVar = vm.newFunction('setVar', function (key, value) {
bru.setVar(vm.dump(key), vm.dump(value));
});
vm.setProp(vm.global, "__bruno__setVar", setVar);
vm.setProp(bruObject, 'setVar', setVar);
setVar.dispose();
let setNextRequest = vm.newFunction('setNextRequest', function (nextRequest) {
bru.setNextRequest(vm.dump(nextRequest));
});
vm.setProp(vm.global, "__bruno__setNextRequest", setNextRequest);
vm.setProp(bruObject, 'setNextRequest', setNextRequest);
setNextRequest.dispose();
let visualize = vm.newFunction('visualize', function (htmlString) {
bru.visualize(vm.dump(htmlString));
});
vm.setProp(vm.global, "__bruno__visualize", visualize);
vm.setProp(bruObject, 'visualize', visualize);
visualize.dispose();
let getSecretVar = vm.newFunction('getSecretVar', function (key) {
return marshallToVm(bru.getSecretVar(vm.dump(key)), vm);
});
vm.setProp(vm.global, "__bruno__getSecretVar", getSecretVar);
vm.setProp(bruObject, 'getSecretVar', getSecretVar);
getSecretVar.dispose();
vm.setProp(vm.global, 'bru', bruObject);
bruObject.dispose();
};
module.exports = addBruShimToContext;

View File

@@ -1,17 +1,19 @@
const { marshallToVm } = require('../utils');
const addBrunoRequestShimToContext = (vm, req) => {
const reqObject = vm.newObject();
const url = marshallToVm(req.getUrl(), vm);
const method = marshallToVm(req.getMethod(), vm);
const headers = marshallToVm(req.getHeaders(), vm);
const body = marshallToVm(req.getBody(), vm);
const timeout = marshallToVm(req.getTimeout(), vm);
vm.setProp(vm.global, '__bruno__req__url', url);
vm.setProp(vm.global, '__bruno__req__method', method);
vm.setProp(vm.global, '__bruno__req__headers', headers);
vm.setProp(vm.global, '__bruno__req__body', body);
vm.setProp(vm.global, '__bruno__req__timeout', timeout);
vm.setProp(reqObject, 'url', url);
vm.setProp(reqObject, 'method', method);
vm.setProp(reqObject, 'headers', headers);
vm.setProp(reqObject, 'body', body);
vm.setProp(reqObject, 'timeout', timeout);
url.dispose();
method.dispose();
@@ -22,86 +24,89 @@ const addBrunoRequestShimToContext = (vm, req) => {
let getUrl = vm.newFunction('getUrl', function () {
return marshallToVm(req.getUrl(), vm);
});
vm.setProp(vm.global, '__bruno__req__getUrl', getUrl);
vm.setProp(reqObject, 'getUrl', getUrl);
getUrl.dispose();
let setUrl = vm.newFunction('setUrl', function (url) {
req.setUrl(vm.dump(url));
});
vm.setProp(vm.global, '__bruno__req__setUrl', setUrl);
vm.setProp(reqObject, 'setUrl', setUrl);
setUrl.dispose();
let getMethod = vm.newFunction('getMethod', function () {
return marshallToVm(req.getMethod(), vm);
});
vm.setProp(vm.global, '__bruno__req__getMethod', getMethod);
vm.setProp(reqObject, 'getMethod', getMethod);
getMethod.dispose();
let getAuthMode = vm.newFunction('getAuthMode', function () {
return marshallToVm(req.getAuthMode(), vm);
});
vm.setProp(vm.global, '__bruno__req__getAuthMode', getAuthMode);
vm.setProp(reqObject, 'getAuthMode', getAuthMode);
getAuthMode.dispose();
let setMethod = vm.newFunction('setMethod', function (method) {
req.setMethod(vm.dump(method));
});
vm.setProp(vm.global, '__bruno__req__setMethod', setMethod);
vm.setProp(reqObject, 'setMethod', setMethod);
setMethod.dispose();
let getHeaders = vm.newFunction('getHeaders', function () {
return marshallToVm(req.getHeaders(), vm);
});
vm.setProp(vm.global, '__bruno__req__getHeaders', getHeaders);
vm.setProp(reqObject, 'getHeaders', getHeaders);
getHeaders.dispose();
let setHeaders = vm.newFunction('setHeaders', function (headers) {
req.setHeaders(vm.dump(headers));
});
vm.setProp(vm.global, '__bruno__req__setHeaders', setHeaders);
vm.setProp(reqObject, 'setHeaders', setHeaders);
setHeaders.dispose();
let getHeader = vm.newFunction('getHeader', function (name) {
return marshallToVm(req.getHeader(vm.dump(name)), vm);
});
vm.setProp(vm.global, '__bruno__req__getHeader', getHeader);
vm.setProp(reqObject, 'getHeader', getHeader);
getHeader.dispose();
let setHeader = vm.newFunction('setHeader', function (name, value) {
req.setHeader(vm.dump(name), vm.dump(value));
});
vm.setProp(vm.global, '__bruno__req__setHeader', setHeader);
vm.setProp(reqObject, 'setHeader', setHeader);
setHeader.dispose();
let getBody = vm.newFunction('getBody', function () {
return marshallToVm(req.getBody(), vm);
});
vm.setProp(vm.global, '__bruno__req__getBody', getBody);
vm.setProp(reqObject, 'getBody', getBody);
getBody.dispose();
let setBody = vm.newFunction('setBody', function (data) {
req.setBody(vm.dump(data));
});
vm.setProp(vm.global, '__bruno__req__setBody', setBody);
vm.setProp(reqObject, 'setBody', setBody);
setBody.dispose();
let setMaxRedirects = vm.newFunction('setMaxRedirects', function (maxRedirects) {
req.setMaxRedirects(vm.dump(maxRedirects));
});
vm.setProp(vm.global, '__bruno__req__setMaxRedirects', setMaxRedirects);
vm.setProp(reqObject, 'setMaxRedirects', setMaxRedirects);
setMaxRedirects.dispose();
let getTimeout = vm.newFunction('getTimeout', function () {
return marshallToVm(req.getTimeout(), vm);
});
vm.setProp(vm.global, '__bruno__req__getTimeout', getTimeout);
vm.setProp(reqObject, 'getTimeout', getTimeout);
getTimeout.dispose();
let setTimeout = vm.newFunction('setTimeout', function (timeout) {
req.setTimeout(vm.dump(timeout));
});
vm.setProp(vm.global, '__bruno__req__setTimeout', setTimeout);
vm.setProp(reqObject, 'setTimeout', setTimeout);
setTimeout.dispose();
vm.setProp(vm.global, 'req', reqObject);
reqObject.dispose();
};
module.exports = addBrunoRequestShimToContext;

View File

@@ -1,16 +1,17 @@
const { marshallToVm } = require('../utils');
const addBrunoResponseShimToContext = (vm, res) => {
const resObject = vm.newObject();
const status = marshallToVm(res?.status, vm);
const headers = marshallToVm(res?.headers, vm);
const body = marshallToVm(res?.body, vm);
const responseTime = marshallToVm(res?.responseTime, vm);
vm.setProp(vm.global, '__bruno__res__status', status);
vm.setProp(vm.global, '__bruno__res__headers', headers);
vm.setProp(vm.global, '__bruno__res__body', body);
vm.setProp(vm.global, '__bruno__res__responseTime', responseTime);
vm.setProp(resObject, 'status', status);
vm.setProp(resObject, 'headers', headers);
vm.setProp(resObject, 'body', body);
vm.setProp(resObject, 'responseTime', responseTime);
status.dispose();
headers.dispose();
@@ -20,32 +21,35 @@ const addBrunoResponseShimToContext = (vm, res) => {
let getStatus = vm.newFunction('getStatus', function () {
return marshallToVm(res.getStatus(), vm);
});
vm.setProp(vm.global, '__bruno__res__getStatus', getStatus);
vm.setProp(resObject, 'getStatus', getStatus);
getStatus.dispose();
let getHeader = vm.newFunction('getHeader', function (name) {
return marshallToVm(res.getHeader(vm.dump(name)), vm);
});
vm.setProp(vm.global, '__bruno__res__getHeader', getHeader);
vm.setProp(resObject, 'getHeader', getHeader);
getHeader.dispose();
let getHeaders = vm.newFunction('getHeaders', function () {
return marshallToVm(res.getHeaders(), vm);
});
vm.setProp(vm.global, '__bruno__res__getHeaders', getHeaders);
vm.setProp(resObject, 'getHeaders', getHeaders);
getHeaders.dispose();
let getBody = vm.newFunction('getBody', function () {
return marshallToVm(res.getBody(), vm);
});
vm.setProp(vm.global, '__bruno__res__getBody', getBody);
vm.setProp(resObject, 'getBody', getBody);
getBody.dispose();
let getResponseTime = vm.newFunction('getResponseTime', function () {
return marshallToVm(res.getResponseTime(), vm);
});
vm.setProp(vm.global, '__bruno__res__getResponseTime', getResponseTime);
vm.setProp(resObject, 'getResponseTime', getResponseTime);
getResponseTime.dispose();
vm.setProp(vm.global, 'res', resObject);
resObject.dispose();
};
module.exports = addBrunoResponseShimToContext;

View File

@@ -0,0 +1,44 @@
const addConsoleShimToContext = (vm, console) => {
const consoleHandle = vm.newObject();
const logHandle = vm.newFunction('log', (...args) => {
const nativeArgs = args.map(vm.dump);
console?.log && console.log(...nativeArgs);
});
const debugHandle = vm.newFunction('debug', (...args) => {
const nativeArgs = args.map(vm.dump);
console?.debug && console.debug(...nativeArgs);
});
const infoHandle = vm.newFunction('info', (...args) => {
const nativeArgs = args.map(vm.dump);
console?.info && console.info(...nativeArgs);
});
const warnHandle = vm.newFunction('warn', (...args) => {
const nativeArgs = args.map(vm.dump);
console?.warn && console.warn(...nativeArgs);
});
const errorHandle = vm.newFunction('error', (...args) => {
const nativeArgs = args.map(vm.dump);
console?.error && console.error(...nativeArgs);
});
vm.setProp(consoleHandle, 'log', logHandle);
vm.setProp(consoleHandle, 'debug', debugHandle);
vm.setProp(consoleHandle, 'info', infoHandle);
vm.setProp(consoleHandle, 'warn', warnHandle);
vm.setProp(consoleHandle, 'error', errorHandle);
vm.setProp(vm.global, 'console', consoleHandle);
consoleHandle.dispose();
logHandle.dispose();
debugHandle.dispose();
infoHandle.dispose();
warnHandle.dispose();
errorHandle.dispose();
};
module.exports = addConsoleShimToContext;

View File

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

View File

@@ -0,0 +1,5 @@
const { nanoid } = require('nanoid');
const addNanoidShimToContext = async (context) => {};
module.exports = addNanoidShimToContext;

View File

@@ -4,14 +4,62 @@ const addBruShimToContext = (vm, __brunoTestResults) => {
let addResult = vm.newFunction('addResult', function (v) {
__brunoTestResults.addResult(vm.dump(v));
});
vm.setProp(vm.global, "__bruno__addResult", addResult);
vm.setProp(vm.global, '__bruno__addResult', addResult);
addResult.dispose();
let getResults = vm.newFunction('getResults', function () {
return marshallToVm(__brunoTestResults.getResults(), vm);
});
vm.setProp(vm.global, "__bruno__getResults", getResults);
vm.setProp(vm.global, '__bruno__getResults', getResults);
getResults.dispose();
// vm.evalCode(
// `
// globalThis.expect = require('chai').expect;
// globalThis.assert = require('chai').assert;
// globalThis.__brunoTestResults = {
// addResult: globalThis.addResult,
// getResults: globalThis.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 {
// __brunoTestResults.addResult({
// description,
// status: "fail",
// error: error.message || "An unexpected error occurred.",
// });
// }
// console.log(error);
// }
// };
// let foobar = 'foobar3000';
// log("from test shim");
// globalThis.test = Test(__brunoTestResults);
// `
// );
};
module.exports = addBruShimToContext;

View File

@@ -2,18 +2,16 @@ const marshallToVm = (value, vm) => {
if (value === undefined) {
return vm.undefined;
}
if (value === null) {
return vm.null;
}
if (typeof value === "string") {
if (typeof value === 'string') {
return vm.newString(value);
} else if (typeof value === "number") {
} else if (typeof value === 'number') {
return vm.newNumber(value);
} else if (typeof value === "boolean") {
} else if (typeof value === 'boolean') {
return vm.newBoolean(value);
} else if (typeof value === "object") {
} else if (typeof value === 'object') {
if (Array.isArray(value)) {
const arr = vm.newArray();
for (let i = 0; i < value.length; i++) {