Skip to content

Latest commit

 

History

History
129 lines (104 loc) · 3.58 KB

File metadata and controls

129 lines (104 loc) · 3.58 KB

Create a npm package which provides a unified API(function) to execute different programming language code in users browser

We need to utilize web workers to not block the main thread and keep performance in mind in every step. Our final result would be to publish the package to npm hence create documentation/readme considreing that.

We only need to focus on Phase 1 for now.

Phase 1 — Easiest (Runs natively or stable WASM builds exist)

1. JavaScript / TypeScript
    - Already runs in the browser (no extra runtime).
    - Can use eval() or better: Web Workers for isolation.
    - For Node.js-like environment → WebContainers(by StackBlitz).

2. Python (via Pyodide / PyScript)
    - Pyodide (official CPython → WebAssembly) is production ready.
    - ~7–10 MB load, but works well once cached.

3. Lua (via Fengari)
    - Tiny interpreter (~1 MB) compiled to JS.
    - Super lightweight, very easy to embed.

Phase 2 — Medium Complexity (but still feasible)

1. C / C++ (via Emscripten)
    - You can pre-compile code snippets to WASM.
    - Tricky for "compile on the fly", but doable with client-side Clang+LLVM WASM (heavy).
    - Better to restrict to pre-built C runtimes for exercises.

2. Ruby (via Opal or WASM MRI builds)
    - Opal compiles Ruby → JS.
    - Lightweight, but limited (not full Ruby stdlib).
    - WASM MRI ports exist, but heavy.

Unified API example :

import { runCode } from "my-unified-runner";

const result = await runCode({ language: "python", // "javascript" | "python" | "lua" code: "print(1+2)", stdin: "", timeout: 2000 });

console.log(result); /* { stdout: "3\n", stderr: "", exitCode: 0, timeMs: 15 } */

// JS Runner export async function runJavaScript(code: string, stdin: string) { try { let stdout = ""; const log = console.log; console.log = (...args) => { stdout += args.join(" ") + "\n"; }; eval(code); console.log = log; return { stdout, stderr: "", exitCode: 0 }; } catch (err) { return { stdout: "", stderr: String(err), exitCode: 1 }; } }

// Python Runner import { loadPyodide } from "pyodide";

let pyodide: any;

export async function runPython(code: string) { if (!pyodide) { pyodide = await loadPyodide(); // one-time load } try { const result = await pyodide.runPythonAsync(code); return { stdout: String(result), stderr: "", exitCode: 0 }; } catch (err) { return { stdout: "", stderr: String(err), exitCode: 1 }; } }

// Lua

import { lua, lauxlib, lualib, to_jsstring } from "fengari";

export async function runLua(code: string) { try { const L = lauxlib.luaL_newstate(); lualib.luaL_openlibs(L); if (lauxlib.luaL_dostring(L, code) !== lua.LUA_OK) { throw new Error(to_jsstring(lua.lua_tostring(L, -1))); } return { stdout: "", stderr: "", exitCode: 0 }; } catch (err) { return { stdout: "", stderr: String(err), exitCode: 1 }; } }

// Manager

import { runJavaScript } from "./runtimes/jsRunner"; import { runPython } from "./runtimes/pyRunner"; import { runLua } from "./runtimes/luaRunner";

export async function runCode({ language, code, stdin, timeout }) { const start = performance.now(); let result; switch (language) { case "javascript": result = await runJavaScript(code, stdin); break; case "python": result = await runPython(code); break; case "lua": result = await runLua(code); break; default: throw new Error("Unsupported language: " + language); } result.timeMs = performance.now() - start; return result; }