From e81029f28be31deafb2f95dcb597ee4b02587c0e Mon Sep 17 00:00:00 2001 From: lohxt1 Date: Fri, 16 Aug 2024 22:24:21 +0530 Subject: [PATCH] wip: code cleanup, added axios, nanoid shims for quickjs vm --- .../bruno-js/src/sandbox/quickjs/index.js | 91 +++---------------- .../src/sandbox/quickjs/shims/lib/axios.js | 72 +++++++++++++++ .../src/sandbox/quickjs/shims/lib/index.js | 6 +- .../src/sandbox/quickjs/shims/lib/nanoid.js | 21 ++++- .../src/sandbox/quickjs/shims/sleep.js | 14 +++ .../src/sandbox/quickjs/shims/test.js | 86 +++++++++--------- 6 files changed, 163 insertions(+), 127 deletions(-) create mode 100644 packages/bruno-js/src/sandbox/quickjs/shims/lib/axios.js create mode 100644 packages/bruno-js/src/sandbox/quickjs/shims/sleep.js diff --git a/packages/bruno-js/src/sandbox/quickjs/index.js b/packages/bruno-js/src/sandbox/quickjs/index.js index 5f09ffe99..6aa3b5df8 100644 --- a/packages/bruno-js/src/sandbox/quickjs/index.js +++ b/packages/bruno-js/src/sandbox/quickjs/index.js @@ -8,6 +8,7 @@ const { newQuickJSWASMModule, memoizePromiseFactory } = require('quickjs-emscrip // 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'); let QuickJSSyncContext; const loader = memoizePromiseFactory(() => newQuickJSWASMModule()); @@ -33,17 +34,6 @@ const executeQuickJsVm = ({ script: externalScript, context: externalContext, sc req && addBrunoRequestShimToContext(vm, req); res && addBrunoResponseShimToContext(vm, res); - //////////////////////////////////////////////////////////////////////////////// - - 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 = `\`${externalScript}\`;`; const jsExpressionText = `${externalScript};`; @@ -81,15 +71,15 @@ const executeQuickJsVmAsync = async ({ const vm = module.newContext(); const bundledCode = getBundledCode?.toString() || ''; - let bundledScript = ` - (${bundledCode})() - `; - bundledScript += ` - globalThis.require = (module) => { - return globalThis.requireObject[module]; - } - `; + vm.evalCode( + ` + (${bundledCode})() + globalThis.require = (module) => { + return globalThis.requireObject[module]; + } + ` + ); const { bru, req, res, test, __brunoTestResults, console: consoleFn } = externalContext; @@ -97,72 +87,13 @@ const executeQuickJsVmAsync = async ({ req && addBrunoRequestShimToContext(vm, req); res && addBrunoResponseShimToContext(vm, res); consoleFn && addConsoleShimToContext(vm, consoleFn); + addSleepShimToContext(vm); - // await addLibraryShimsToContext(context); + await addLibraryShimsToContext(vm); test && __brunoTestResults && addTestShimToContext(vm, __brunoTestResults); - bundledScript += ` - 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.", - }); - } - } - }; - - 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); diff --git a/packages/bruno-js/src/sandbox/quickjs/shims/lib/axios.js b/packages/bruno-js/src/sandbox/quickjs/shims/lib/axios.js new file mode 100644 index 000000000..2f0fc0789 --- /dev/null +++ b/packages/bruno-js/src/sandbox/quickjs/shims/lib/axios.js @@ -0,0 +1,72 @@ +const axios = require('axios'); +const { cleanJson } = require('../../../../utils'); +const { marshallToVm } = require('../../utils'); + +const methods = ['get', 'post', 'put', 'patch', 'delete']; + +const addAxiosShimToContext = async (vm) => { + methods?.forEach((method) => { + const axiosHandle = vm.newFunction(method, (...args) => { + const nativeArgs = args.map(vm.dump); + const promise = vm.newPromise(); + axios[method](...nativeArgs) + .then((response) => { + const { status, headers, data } = response || {}; + 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; + }); + axiosHandle.consume((handle) => vm.setProp(vm.global, `__bruno__axios__${method}`, handle)); + }); + + const axiosHandle = vm.newFunction('axios', (...args) => { + const nativeArgs = args.map(vm.dump); + const promise = vm.newPromise(); + axios(...nativeArgs) + .then((response) => { + const { status, headers, data } = response || {}; + 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; + }); + axiosHandle.consume((handle) => vm.setProp(vm.global, `__bruno__axios`, handle)); + + vm.evalCode( + ` + globalThis.axios = __bruno__axios; + ${methods + ?.map((method) => { + return `globalThis.axios.${method} = __bruno__axios__${method};`; + }) + ?.join('\n')} + globalThis.requireObject = { + ...globalThis.requireObject, + axios: globalThis.axios, + } + ` + ); +}; + +module.exports = addAxiosShimToContext; diff --git a/packages/bruno-js/src/sandbox/quickjs/shims/lib/index.js b/packages/bruno-js/src/sandbox/quickjs/shims/lib/index.js index f15d1ef6e..78cc730e7 100644 --- a/packages/bruno-js/src/sandbox/quickjs/shims/lib/index.js +++ b/packages/bruno-js/src/sandbox/quickjs/shims/lib/index.js @@ -1,7 +1,9 @@ +const addAxiosShimToContext = require('./axios'); const addNanoidShimToContext = require('./nanoid'); -const addLibraryShimsToContext = async (context) => { - await addNanoidShimToContext(context); +const addLibraryShimsToContext = async (vm) => { + await addNanoidShimToContext(vm); + await addAxiosShimToContext(vm); }; module.exports = addLibraryShimsToContext; diff --git a/packages/bruno-js/src/sandbox/quickjs/shims/lib/nanoid.js b/packages/bruno-js/src/sandbox/quickjs/shims/lib/nanoid.js index 04107bb75..66b4ba38a 100644 --- a/packages/bruno-js/src/sandbox/quickjs/shims/lib/nanoid.js +++ b/packages/bruno-js/src/sandbox/quickjs/shims/lib/nanoid.js @@ -1,5 +1,24 @@ const { nanoid } = require('nanoid'); +const { marshallToVm } = require('../../utils'); -const addNanoidShimToContext = async (context) => {}; +const addNanoidShimToContext = async (vm) => { + let _nanoid = vm.newFunction('nanoid', function () { + let v = nanoid(); + console.log(v); + return marshallToVm(v, vm); + }); + vm.setProp(vm.global, '__bruno__nanoid', _nanoid); + _nanoid.dispose(); + vm.evalCode( + ` + globalThis.nanoid = {}; + globalThis.nanoid.nanoid = globalThis.__bruno__nanoid; + globalThis.requireObject = { + ...globalThis.requireObject, + 'nanoid': globalThis.nanoid + } + ` + ); +}; module.exports = addNanoidShimToContext; diff --git a/packages/bruno-js/src/sandbox/quickjs/shims/sleep.js b/packages/bruno-js/src/sandbox/quickjs/shims/sleep.js new file mode 100644 index 000000000..79fd146f9 --- /dev/null +++ b/packages/bruno-js/src/sandbox/quickjs/shims/sleep.js @@ -0,0 +1,14 @@ +const addSleepShimToContext = (vm) => { + const sleepHandle = 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; + }); + sleepHandle.consume((handle) => vm.setProp(vm.global, 'sleep', handle)); +}; + +module.exports = addSleepShimToContext; diff --git a/packages/bruno-js/src/sandbox/quickjs/shims/test.js b/packages/bruno-js/src/sandbox/quickjs/shims/test.js index f7a928101..b6cd93e8e 100644 --- a/packages/bruno-js/src/sandbox/quickjs/shims/test.js +++ b/packages/bruno-js/src/sandbox/quickjs/shims/test.js @@ -13,53 +13,51 @@ const addBruShimToContext = (vm, __brunoTestResults) => { vm.setProp(vm.global, '__bruno__getResults', getResults); getResults.dispose(); - // vm.evalCode( - // ` - // globalThis.expect = require('chai').expect; - // globalThis.assert = require('chai').assert; + vm.evalCode( + ` + globalThis.expect = require('chai').expect; + globalThis.assert = require('chai').assert; - // globalThis.__brunoTestResults = { - // addResult: globalThis.addResult, - // getResults: globalThis.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 { - // __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); - // ` - // ); + globalThis.Test = (__brunoTestResults) => async (description, callback) => { + try { + await callback(); + __brunoTestResults.__bruno__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 = Test(__brunoTestResults); + ` + ); }; module.exports = addBruShimToContext;