import ExecutionController from "./execution-controller"; import { LanguageEngine, StepExecutionResult } from "./types"; import { WorkerAckType, WorkerRequestData, WorkerResponseData, } from "./worker-constants"; /** Create a worker response for update acknowledgement */ const ackMessage = (state: WorkerAckType): WorkerResponseData => ({ type: "ack", data: state, }); /** Create a worker response for execution result */ const resultMessage = ( result: StepExecutionResult ): WorkerResponseData => ({ type: "result", data: result, }); /** Initialize the execution controller */ const initController = () => { postMessage(ackMessage("init")); }; /** * Reset the state of the controller and engine, to * prepare for execution of a new program. */ const resetController = (controller: ExecutionController) => { controller.resetState(); postMessage(ackMessage("reset")); }; /** * Load program code into the engine. * @param code Code content of the program */ const prepare = ( controller: ExecutionController, { code, input }: { code: string; input: string } ) => { controller.prepare(code, input); postMessage(ackMessage("prepare")); }; /** * Update debugging breakpoints * @param points List of line numbers having breakpoints */ const updateBreakpoints = ( controller: ExecutionController, points: number[] ) => { controller.updateBreakpoints(points); postMessage(ackMessage("bp-update")); }; /** * Execute the entire program loaded on engine, * and return result of execution. */ const execute = (controller: ExecutionController, interval: number) => { controller.executeAll({ interval, onResult: (res) => postMessage(resultMessage(res)), }); }; /** Trigger pause in program execution */ const pauseExecution = async (controller: ExecutionController) => { await controller.pauseExecution(); postMessage(ackMessage("pause")); }; /** Run a single execution step */ const executeStep = (controller: ExecutionController) => { const result = controller.executeStep(); postMessage(resultMessage(result)); }; /** * Create an execution controller worker script with the given engine. * @param engine Language engine to create worker for */ export const setupWorker = (engine: LanguageEngine) => { const controller = new ExecutionController(engine); addEventListener("message", async (ev: MessageEvent) => { if (ev.data.type === "Init") return initController(); if (ev.data.type === "Reset") return resetController(controller); if (ev.data.type === "Prepare") return prepare(controller, ev.data.params); if (ev.data.type === "Execute") return execute(controller, ev.data.params.interval); if (ev.data.type === "Pause") return await pauseExecution(controller); if (ev.data.type === "ExecuteStep") return executeStep(controller); if (ev.data.type === "UpdateBreakpoints") return updateBreakpoints(controller, ev.data.params.points); throw new Error("Invalid worker message type"); }); };