Files
deno-isolator/worker.ts
2025-07-27 22:02:19 +10:00

97 lines
2.8 KiB
TypeScript

// isolator/worker.ts
// No module cache to ensure fresh code for every execution.
const States = Object.freeze({
SUCCESS: "SUCCESS",
NOT_A_FUNCTION: "NOT_A_FUNCTION",
SCRIPT_ERROR: "ERROR",
});
self.onmessage = async (e) => {
const { code, request, environment, name } = e.data;
const logs: any[] = [];
const startTime = performance.now();
// Temporarily override console.log and console.error to capture logs
const oldConsoleLog = console.log;
const oldConsoleError = console.error;
console.log = (...args) => {
logs.push(args);
oldConsoleLog.apply(console, args);
};
console.error = (...args) => {
logs.push(args);
oldConsoleError.apply(console, args);
};
try {
// Make the environment object and response helpers available globally.
(self as any).environment = environment;
(self as any).FUNCTION_NAME = name;
(self as any).Response = (body = "", headers = {}, status = 200) => ({
body,
status,
headers,
});
(self as any).JsonResponse = (body = {}, headers = {}, status = 200) =>
(self as any).Response(
JSON.stringify(body),
{ "Content-Type": "application/json", ...headers },
status
);
(self as any).HtmlResponse = (body = "", headers = {}, status = 200) =>
(self as any).Response(
body,
{ "Content-Type": "text/html", ...headers },
status
);
(self as any).TextResponse = (body = "", headers = {}, status = 200) =>
(self as any).Response(
body,
{ "Content-Type": "text/plain", ...headers },
status
);
// Use a data URL to import the user's code as a fresh ES module on every execution.
const dataUrl = `data:text/javascript;base64,${btoa(
unescape(encodeURIComponent(code))
)}`;
const userModule = await import(dataUrl);
if (typeof userModule.default !== "function") {
throw new Error(
"Module does not have a default export or the export is not a function."
);
}
const userFn = userModule.default;
const result = await userFn(request);
const executionTime = performance.now() - startTime;
self.postMessage({
status: States.SUCCESS,
result,
logs,
environment: (self as any).environment, // Return the mutated environment.
execution_time: executionTime,
});
} catch (err) {
const executionTime = performance.now() - startTime;
self.postMessage({
status: States.SCRIPT_ERROR,
result: {
name: err.name,
message: err.message,
stack: err.stack,
},
logs,
environment,
execution_time: executionTime,
});
} finally {
// Restore original console functions
console.log = oldConsoleLog;
console.error = oldConsoleError;
}
};