chore: migrate Node.js implementation for js-sandbox to isolated-vm (#3973)

Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
This commit is contained in:
James George
2024-04-19 08:38:46 -07:00
committed by GitHub
parent a079e0f04b
commit 22c6eabd13
52 changed files with 1028 additions and 285 deletions

View File

@@ -0,0 +1,2 @@
export { runPreRequestScript } from "./pre-request"
export { runTestScript } from "./test-runner"

View File

@@ -0,0 +1,24 @@
import * as E from "fp-ts/Either"
import { TestResult } from "~/types"
import Worker from "./worker?worker&inline"
export const runPreRequestScript = (
preRequestScript: string,
envs: TestResult["envs"]
): Promise<E.Either<string, TestResult["envs"]>> =>
new Promise((resolve) => {
const worker = new Worker()
// Listen for the results from the web worker
worker.addEventListener("message", (event: MessageEvent) =>
resolve(event.data.results)
)
// Send the script to the web worker
worker.postMessage({
preRequestScript,
envs,
})
})

View File

@@ -0,0 +1,33 @@
import * as TE from "fp-ts/TaskEither"
import { TestResult } from "~/types"
import { getPreRequestScriptMethods } from "~/shared-utils"
const executeScriptInContext = (
preRequestScript: string,
envs: TestResult["envs"]
): TE.TaskEither<string, TestResult["envs"]> => {
try {
const { pw, updatedEnvs } = getPreRequestScriptMethods(envs)
// Create a function from the pre request script using the `Function` constructor
const executeScript = new Function("pw", preRequestScript)
// Execute the script
executeScript(pw)
return TE.right(updatedEnvs)
} catch (error) {
return TE.left(`Script execution failed: ${(error as Error).message}`)
}
}
// Listen for messages from the main thread
self.addEventListener("message", async (event) => {
const { preRequestScript, envs } = event.data
const results = await executeScriptInContext(preRequestScript, envs)()
// Post the result back to the main thread
self.postMessage({ results })
})

View File

@@ -0,0 +1,27 @@
import * as E from "fp-ts/Either"
import { SandboxTestResult, TestResponse, TestResult } from "~/types"
import Worker from "./worker?worker&inline"
export const runTestScript = (
testScript: string,
envs: TestResult["envs"],
response: TestResponse
): Promise<E.Either<string, SandboxTestResult>> => {
return new Promise((resolve) => {
const worker = new Worker()
// Listen for the results from the web worker
worker.addEventListener("message", (event: MessageEvent) =>
resolve(event.data.results)
)
// Send the script to the web worker
worker.postMessage({
testScript,
envs,
response,
})
})
}

View File

@@ -0,0 +1,46 @@
import * as E from "fp-ts/Either"
import * as TE from "fp-ts/TaskEither"
import { SandboxTestResult, TestResponse, TestResult } from "~/types"
import {
getTestRunnerScriptMethods,
preventCyclicObjects,
} from "~/shared-utils"
const executeScriptInContext = (
testScript: string,
envs: TestResult["envs"],
response: TestResponse
): TE.TaskEither<string, SandboxTestResult> => {
try {
const responseObjHandle = preventCyclicObjects(response)
if (E.isLeft(responseObjHandle)) {
return TE.left(`Response marshalling failed: ${responseObjHandle.left}`)
}
const { pw, testRunStack, updatedEnvs } = getTestRunnerScriptMethods(envs)
// Create a function from the test script using the `Function` constructor
const executeScript = new Function("pw", testScript)
// Execute the script
executeScript({ ...pw, response: responseObjHandle.right })
return TE.right(<SandboxTestResult>{
tests: testRunStack[0],
envs: updatedEnvs,
})
} catch (error) {
return TE.left(`Script execution failed: ${(error as Error).message}`)
}
}
// Listen for messages from the main thread
self.addEventListener("message", async (event) => {
const { testScript, envs, response } = event.data
const results = await executeScriptInContext(testScript, envs, response)()
// Post the result back to the main thread
self.postMessage({ results })
})