diff options
Diffstat (limited to 'worker')
| -rw-r--r-- | worker/php/biome.json | 64 | ||||
| -rw-r--r-- | worker/php/exec.mjs | 30 | ||||
| -rw-r--r-- | worker/php/index.mjs | 44 | ||||
| -rw-r--r-- | worker/php/lib.mjs | 118 | ||||
| -rw-r--r-- | worker/php/lib.test.mjs | 276 | ||||
| -rw-r--r-- | worker/php/package.json | 34 | ||||
| -rw-r--r-- | worker/php/vitest.config.mjs | 2 |
7 files changed, 284 insertions, 284 deletions
diff --git a/worker/php/biome.json b/worker/php/biome.json index 7f791c6..f0aaa73 100644 --- a/worker/php/biome.json +++ b/worker/php/biome.json @@ -1,34 +1,34 @@ { - "$schema": "https://biomejs.dev/schemas/2.3.15/schema.json", - "vcs": { - "enabled": false, - "clientKind": "git", - "useIgnoreFile": false - }, - "files": { - "ignoreUnknown": false, - "includes": ["**"] - }, - "formatter": { - "enabled": true, - "indentStyle": "tab" - }, - "assist": { - "actions": { - "source": { - "organizeImports": "on" - } - } - }, - "linter": { - "enabled": true, - "rules": { - "recommended": true - } - }, - "javascript": { - "formatter": { - "quoteStyle": "double" - } - } + "$schema": "https://biomejs.dev/schemas/2.3.15/schema.json", + "vcs": { + "enabled": false, + "clientKind": "git", + "useIgnoreFile": false + }, + "files": { + "ignoreUnknown": false, + "includes": ["**"] + }, + "formatter": { + "enabled": true, + "indentStyle": "space" + }, + "assist": { + "actions": { + "source": { + "organizeImports": "on" + } + } + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true + } + }, + "javascript": { + "formatter": { + "quoteStyle": "double" + } + } } diff --git a/worker/php/exec.mjs b/worker/php/exec.mjs index 7403dfc..f1cb361 100644 --- a/worker/php/exec.mjs +++ b/worker/php/exec.mjs @@ -2,22 +2,22 @@ import { buildResult, createIOCallbacks, preprocessCode } from "./lib.mjs"; import PHPWasm from "./php-wasm.js"; process.once("message", async ({ code: originalCode, input }) => { - const code = preprocessCode(originalCode); - const io = createIOCallbacks(input); + const code = preprocessCode(originalCode); + const io = createIOCallbacks(input); - const { ccall } = await PHPWasm({ - stdin: io.stdin, - stdout: io.stdout, - stderr: io.stderr, - }); + const { ccall } = await PHPWasm({ + stdin: io.stdin, + stdout: io.stdout, + stderr: io.stderr, + }); - let err; - let result; - try { - result = ccall("php_wasm_run", "number", ["string"], [code]); - } catch (e) { - err = e; - } + let err; + let result; + try { + result = ccall("php_wasm_run", "number", ["string"], [code]); + } catch (e) { + err = e; + } - process.send(buildResult(err, result, io.getStdout, io.getStderr)); + process.send(buildResult(err, result, io.getStdout, io.getStderr)); }); diff --git a/worker/php/index.mjs b/worker/php/index.mjs index 9950ffa..c2bd818 100644 --- a/worker/php/index.mjs +++ b/worker/php/index.mjs @@ -3,37 +3,37 @@ import { serve } from "@hono/node-server"; import { Hono } from "hono"; const execPhp = (code, input, timeoutMsec) => { - return new Promise((resolve, _reject) => { - const proc = fork("./exec.mjs"); + return new Promise((resolve, _reject) => { + const proc = fork("./exec.mjs"); - proc.send({ code, input }); + proc.send({ code, input }); - proc.on("message", (result) => { - resolve(result); - proc.kill(); - }); + proc.on("message", (result) => { + resolve(result); + proc.kill(); + }); - setTimeout(() => { - resolve({ - status: "timeout", - stdout: "", - stderr: `Time Limit Exceeded: ${timeoutMsec} msec`, - }); - proc.kill(); - }, timeoutMsec); - }); + setTimeout(() => { + resolve({ + status: "timeout", + stdout: "", + stderr: `Time Limit Exceeded: ${timeoutMsec} msec`, + }); + proc.kill(); + }, timeoutMsec); + }); }; const app = new Hono(); app.post("/exec", async (c) => { - console.log("worker/exec"); - const { code, stdin, max_duration_ms } = await c.req.json(); - const result = await execPhp(code, stdin, max_duration_ms); - return c.json(result); + console.log("worker/exec"); + const { code, stdin, max_duration_ms } = await c.req.json(); + const result = await execPhp(code, stdin, max_duration_ms); + return c.json(result); }); serve({ - fetch: app.fetch, - port: 80, + fetch: app.fetch, + port: 80, }); diff --git a/worker/php/lib.mjs b/worker/php/lib.mjs index 4a34733..d877856 100644 --- a/worker/php/lib.mjs +++ b/worker/php/lib.mjs @@ -10,70 +10,70 @@ const PRELUDE = ` const BUFFER_MAX = 10 * 1024; export function preprocessCode(originalCode) { - if (originalCode.startsWith("<?php")) { - return PRELUDE + originalCode.slice(5); - } - if (originalCode.startsWith("<?")) { - return PRELUDE + originalCode.slice(2); - } - return PRELUDE + originalCode; + if (originalCode.startsWith("<?php")) { + return PRELUDE + originalCode.slice(5); + } + if (originalCode.startsWith("<?")) { + return PRELUDE + originalCode.slice(2); + } + return PRELUDE + originalCode; } export function createIOCallbacks(input) { - let stdinPos = 0; - const stdinBuf = Buffer.from(input); - let stdoutPos = 0; - const stdoutBuf = Buffer.alloc(BUFFER_MAX); - let stderrPos = 0; - const stderrBuf = Buffer.alloc(BUFFER_MAX); + let stdinPos = 0; + const stdinBuf = Buffer.from(input); + let stdoutPos = 0; + const stdoutBuf = Buffer.alloc(BUFFER_MAX); + let stderrPos = 0; + const stderrBuf = Buffer.alloc(BUFFER_MAX); - return { - stdin: () => { - if (stdinBuf.length <= stdinPos) { - return null; - } - return stdinBuf.readUInt8(stdinPos++); - }, - stdout: (asciiCode) => { - if (asciiCode === null) { - return; - } - if (BUFFER_MAX <= stdoutPos) { - return; - } - stdoutBuf.writeUInt8( - asciiCode < 0 ? asciiCode + 256 : asciiCode, - stdoutPos++, - ); - }, - stderr: (asciiCode) => { - if (asciiCode === null) { - return; - } - if (BUFFER_MAX <= stderrPos) { - return; - } - stderrBuf.writeUInt8( - asciiCode < 0 ? asciiCode + 256 : asciiCode, - stderrPos++, - ); - }, - getStdout: () => stdoutBuf.subarray(0, stdoutPos).toString(), - getStderr: () => stderrBuf.subarray(0, stderrPos).toString(), - }; + return { + stdin: () => { + if (stdinBuf.length <= stdinPos) { + return null; + } + return stdinBuf.readUInt8(stdinPos++); + }, + stdout: (asciiCode) => { + if (asciiCode === null) { + return; + } + if (BUFFER_MAX <= stdoutPos) { + return; + } + stdoutBuf.writeUInt8( + asciiCode < 0 ? asciiCode + 256 : asciiCode, + stdoutPos++, + ); + }, + stderr: (asciiCode) => { + if (asciiCode === null) { + return; + } + if (BUFFER_MAX <= stderrPos) { + return; + } + stderrBuf.writeUInt8( + asciiCode < 0 ? asciiCode + 256 : asciiCode, + stderrPos++, + ); + }, + getStdout: () => stdoutBuf.subarray(0, stdoutPos).toString(), + getStderr: () => stderrBuf.subarray(0, stderrPos).toString(), + }; } export function buildResult(err, ccallResult, getStdout, getStderr) { - if (err) { - return { - status: "runtime_error", - stdout: getStdout(), - stderr: `${getStderr()}\n${err.toString()}`, - }; - } - return { - status: ccallResult === 0 ? "success" : "runtime_error", - stdout: getStdout(), - stderr: getStderr(), - }; + if (err) { + return { + status: "runtime_error", + stdout: getStdout(), + stderr: `${getStderr()}\n${err.toString()}`, + }; + } + return { + status: ccallResult === 0 ? "success" : "runtime_error", + stdout: getStdout(), + stderr: getStderr(), + }; } diff --git a/worker/php/lib.test.mjs b/worker/php/lib.test.mjs index d4f420f..ef01852 100644 --- a/worker/php/lib.test.mjs +++ b/worker/php/lib.test.mjs @@ -2,164 +2,164 @@ import { describe, expect, it } from "vitest"; import { buildResult, createIOCallbacks, preprocessCode } from "./lib.mjs"; describe("preprocessCode", () => { - it("removes <?php tag and prepends PRELUDE", () => { - const result = preprocessCode('<?php echo "hello";'); - expect(result).toContain('echo "hello";'); - expect(result).toContain("error_reporting"); - expect(result).not.toContain("<?php"); - }); + it("removes <?php tag and prepends PRELUDE", () => { + const result = preprocessCode('<?php echo "hello";'); + expect(result).toContain('echo "hello";'); + expect(result).toContain("error_reporting"); + expect(result).not.toContain("<?php"); + }); - it("removes <? short tag and prepends PRELUDE", () => { - const result = preprocessCode('<? echo "hello";'); - expect(result).toContain('echo "hello";'); - expect(result).toContain("error_reporting"); - expect(result).not.toContain("<?"); - }); + it("removes <? short tag and prepends PRELUDE", () => { + const result = preprocessCode('<? echo "hello";'); + expect(result).toContain('echo "hello";'); + expect(result).toContain("error_reporting"); + expect(result).not.toContain("<?"); + }); - it("prepends PRELUDE when no php tag present", () => { - const result = preprocessCode('echo "hello";'); - expect(result).toContain('echo "hello";'); - expect(result).toContain("error_reporting"); - }); + it("prepends PRELUDE when no php tag present", () => { + const result = preprocessCode('echo "hello";'); + expect(result).toContain('echo "hello";'); + expect(result).toContain("error_reporting"); + }); - it("handles empty string", () => { - const result = preprocessCode(""); - expect(result).toContain("error_reporting"); - }); + it("handles empty string", () => { + const result = preprocessCode(""); + expect(result).toContain("error_reporting"); + }); - it("does not remove <?php when not at the start", () => { - const result = preprocessCode('echo "x"; <?php echo "y";'); - expect(result).toContain("<?php"); - }); + it("does not remove <?php when not at the start", () => { + const result = preprocessCode('echo "x"; <?php echo "y";'); + expect(result).toContain("<?php"); + }); }); describe("createIOCallbacks", () => { - describe("stdin", () => { - it("reads input byte by byte", () => { - const io = createIOCallbacks("AB"); - expect(io.stdin()).toBe(65); // 'A' - expect(io.stdin()).toBe(66); // 'B' - }); + describe("stdin", () => { + it("reads input byte by byte", () => { + const io = createIOCallbacks("AB"); + expect(io.stdin()).toBe(65); // 'A' + expect(io.stdin()).toBe(66); // 'B' + }); - it("returns null at EOF", () => { - const io = createIOCallbacks("A"); - io.stdin(); // consume 'A' - expect(io.stdin()).toBeNull(); - expect(io.stdin()).toBeNull(); - }); + it("returns null at EOF", () => { + const io = createIOCallbacks("A"); + io.stdin(); // consume 'A' + expect(io.stdin()).toBeNull(); + expect(io.stdin()).toBeNull(); + }); - it("returns null immediately for empty input", () => { - const io = createIOCallbacks(""); - expect(io.stdin()).toBeNull(); - }); - }); + it("returns null immediately for empty input", () => { + const io = createIOCallbacks(""); + expect(io.stdin()).toBeNull(); + }); + }); - describe("stdout", () => { - it("captures ASCII writes", () => { - const io = createIOCallbacks(""); - io.stdout(72); // 'H' - io.stdout(105); // 'i' - expect(io.getStdout()).toBe("Hi"); - }); + describe("stdout", () => { + it("captures ASCII writes", () => { + const io = createIOCallbacks(""); + io.stdout(72); // 'H' + io.stdout(105); // 'i' + expect(io.getStdout()).toBe("Hi"); + }); - it("ignores null (flush)", () => { - const io = createIOCallbacks(""); - io.stdout(65); - io.stdout(null); - io.stdout(66); - expect(io.getStdout()).toBe("AB"); - }); + it("ignores null (flush)", () => { + const io = createIOCallbacks(""); + io.stdout(65); + io.stdout(null); + io.stdout(66); + expect(io.getStdout()).toBe("AB"); + }); - it("corrects negative asciiCode by adding 256", () => { - const io = createIOCallbacks(""); - // -191 + 256 = 65 = 'A' - io.stdout(-191); - expect(io.getStdout()).toBe("A"); - }); + it("corrects negative asciiCode by adding 256", () => { + const io = createIOCallbacks(""); + // -191 + 256 = 65 = 'A' + io.stdout(-191); + expect(io.getStdout()).toBe("A"); + }); - it("truncates output at 10KB buffer limit", () => { - const io = createIOCallbacks(""); - const limit = 10 * 1024; - for (let i = 0; i < limit + 100; i++) { - io.stdout(65); - } - expect(io.getStdout().length).toBe(limit); - }); - }); + it("truncates output at 10KB buffer limit", () => { + const io = createIOCallbacks(""); + const limit = 10 * 1024; + for (let i = 0; i < limit + 100; i++) { + io.stdout(65); + } + expect(io.getStdout().length).toBe(limit); + }); + }); - describe("stderr", () => { - it("captures ASCII writes", () => { - const io = createIOCallbacks(""); - io.stderr(69); // 'E' - io.stderr(114); // 'r' - expect(io.getStderr()).toBe("Er"); - }); + describe("stderr", () => { + it("captures ASCII writes", () => { + const io = createIOCallbacks(""); + io.stderr(69); // 'E' + io.stderr(114); // 'r' + expect(io.getStderr()).toBe("Er"); + }); - it("ignores null (flush)", () => { - const io = createIOCallbacks(""); - io.stderr(65); - io.stderr(null); - expect(io.getStderr()).toBe("A"); - }); + it("ignores null (flush)", () => { + const io = createIOCallbacks(""); + io.stderr(65); + io.stderr(null); + expect(io.getStderr()).toBe("A"); + }); - it("corrects negative asciiCode by adding 256", () => { - const io = createIOCallbacks(""); - // -156 + 256 = 100 = 'd' - io.stderr(-156); - expect(io.getStderr()).toBe("d"); - }); + it("corrects negative asciiCode by adding 256", () => { + const io = createIOCallbacks(""); + // -156 + 256 = 100 = 'd' + io.stderr(-156); + expect(io.getStderr()).toBe("d"); + }); - it("truncates output at 10KB buffer limit", () => { - const io = createIOCallbacks(""); - const limit = 10 * 1024; - for (let i = 0; i < limit + 100; i++) { - io.stderr(65); - } - expect(io.getStderr().length).toBe(limit); - }); - }); + it("truncates output at 10KB buffer limit", () => { + const io = createIOCallbacks(""); + const limit = 10 * 1024; + for (let i = 0; i < limit + 100; i++) { + io.stderr(65); + } + expect(io.getStderr().length).toBe(limit); + }); + }); }); describe("buildResult", () => { - it("returns success when err is null and result is 0", () => { - const result = buildResult( - null, - 0, - () => "out", - () => "", - ); - expect(result).toEqual({ - status: "success", - stdout: "out", - stderr: "", - }); - }); + it("returns success when err is null and result is 0", () => { + const result = buildResult( + null, + 0, + () => "out", + () => "", + ); + expect(result).toEqual({ + status: "success", + stdout: "out", + stderr: "", + }); + }); - it("returns runtime_error when result is non-zero", () => { - const result = buildResult( - null, - 1, - () => "out", - () => "err", - ); - expect(result).toEqual({ - status: "runtime_error", - stdout: "out", - stderr: "err", - }); - }); + it("returns runtime_error when result is non-zero", () => { + const result = buildResult( + null, + 1, + () => "out", + () => "err", + ); + expect(result).toEqual({ + status: "runtime_error", + stdout: "out", + stderr: "err", + }); + }); - it("returns runtime_error with concatenated stderr when err is thrown", () => { - const err = new Error("fatal"); - const result = buildResult( - err, - undefined, - () => "out", - () => "err", - ); - expect(result.status).toBe("runtime_error"); - expect(result.stdout).toBe("out"); - expect(result.stderr).toContain("err"); - expect(result.stderr).toContain("Error: fatal"); - }); + it("returns runtime_error with concatenated stderr when err is thrown", () => { + const err = new Error("fatal"); + const result = buildResult( + err, + undefined, + () => "out", + () => "err", + ); + expect(result.status).toBe("runtime_error"); + expect(result.stdout).toBe("out"); + expect(result.stderr).toContain("err"); + expect(result.stderr).toContain("Error: fatal"); + }); }); diff --git a/worker/php/package.json b/worker/php/package.json index 12127bd..2430199 100644 --- a/worker/php/package.json +++ b/worker/php/package.json @@ -1,19 +1,19 @@ { - "name": "albatross-2026-worker-php", - "private": true, - "type": "module", - "main": "index.mjs", - "scripts": { - "check": "npm run check:biome", - "check:biome": "biome check --write", - "test": "vitest run" - }, - "dependencies": { - "@hono/node-server": "^1.19.9", - "hono": "^4.11.9" - }, - "devDependencies": { - "@biomejs/biome": "^2.3.15", - "vitest": "^3.2.1" - } + "name": "albatross-2026-worker-php", + "private": true, + "type": "module", + "main": "index.mjs", + "scripts": { + "check": "npm run check:biome", + "check:biome": "biome check --write", + "test": "vitest run" + }, + "dependencies": { + "@hono/node-server": "^1.19.9", + "hono": "^4.11.9" + }, + "devDependencies": { + "@biomejs/biome": "^2.3.15", + "vitest": "^3.2.1" + } } diff --git a/worker/php/vitest.config.mjs b/worker/php/vitest.config.mjs index def6022..77a73cf 100644 --- a/worker/php/vitest.config.mjs +++ b/worker/php/vitest.config.mjs @@ -1,5 +1,5 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ - test: {}, + test: {}, }); |
