-
Notifications
You must be signed in to change notification settings - Fork 1
Add JavaScript runtime with eval-based execution and interrupt via worker termination #91
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Co-authored-by: na-trium-144 <[email protected]>
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
my-code | 35244c8 | Commit Preview URL Branch Preview URL |
Oct 31 2025, 07:38 PM |
Co-authored-by: na-trium-144 <[email protected]>
Co-authored-by: na-trium-144 <[email protected]>
Co-authored-by: na-trium-144 <[email protected]>
Co-authored-by: na-trium-144 <[email protected]>
… interrupt Co-authored-by: na-trium-144 <[email protected]>
| const nextMessageId = useRef<number>(0); | ||
| const isInterrupted = useRef<boolean>(false); | ||
|
|
||
| function postMessage<T>({ type, payload }: MessageToWorker) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot
error: Property 'payload' does not exist on type 'MessageToWorker'.
initとrestorestateメッセージに空のpayloadを追加すると解決すると思います。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in bdfa2a1. Added payload?: undefined to init type and payload: { commands: string[] } to restoreState type.
app/terminal/javascript/runtime.tsx
Outdated
| // Wait for initialization with timeout | ||
| const maxRetries = 50; // 5 seconds total | ||
| let retries = 0; | ||
|
|
||
| await new Promise<void>((resolve, reject) => { | ||
| const checkInterval = setInterval(() => { | ||
| retries++; | ||
| if (retries > maxRetries) { | ||
| clearInterval(checkInterval); | ||
| reject(new Error("Worker initialization timeout")); | ||
| return; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot initializeWorker() の戻り値をPromiseにすればintervalは不要になると思います。
また、再初期化およびrestoreState中にrunCommand()などが呼ばれるのを防ぐためこの部分をmutex.current.runExclusive()で囲ってください。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in bdfa2a1. Changed initializeWorker() to return a Promise and wrapped the entire interrupt() function in mutex.current.runExclusive() to prevent concurrent calls.
app/terminal/javascript/runtime.tsx
Outdated
| // If interrupted or worker was terminated, return appropriate message | ||
| if (isInterrupted.current) { | ||
| return [{ type: "error", message: "実行が中断されました" }]; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot interrupt()内のrejectメッセージ「Worker interrupted」で伝わるので、ここの分岐は不要です。
isInterrupted変数も不要になります。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in bdfa2a1. Removed isInterrupted variable and the conditional check. Now all errors (including "Worker interrupted") are handled uniformly.
public/javascript.worker.js
Outdated
| @@ -0,0 +1,137 @@ | |||
| // JavaScript web worker | |||
| let jsOutput = []; | |||
| let executedCommands = []; // Store successfully executed commands for state recovery | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot interrupt()でworkerをterminateしたらこの変数も消えてしまうので、ここに保存しても意味ないです。runtime.tsx側に保存してください。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in bdfa2a1. Moved executedCommands to runtime.tsx (stored as useRef). The runtime now passes commands to the worker in the restoreState message, so they persist across worker terminations.
…ime, use mutex for interrupt, remove isInterrupted Co-authored-by: na-trium-144 <[email protected]>
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
JavaScript Runtime Implementation - Complete ✅
Summary
This PR implements a JavaScript language runtime API for
app/terminal/, similar to the existing Python runtime (app/terminal/python/runtime.tsx). The implementation uses a web worker with eval() to execute code, and handles interruption by terminating and recreating the worker while restoring state through command replay.Implementation Checklist
app/terminal/javascript/directory structurepublic/javascript.worker.js- Web worker for JavaScript execution with eval()app/terminal/javascript/runtime.tsx- React context provider similar to Python runtimepublic/_headersto add CORS headers for javascript.worker.jsapp/terminal/runtime.tsxto include JavaScript runtime in RuntimeLang type and RuntimeProviderapp/terminal/javascript/page.tsxfor testing the runtimeRecent Changes (Latest Commit)
Fixed all PR review comments:
payload?: undefinedto init and updated restoreState to accept{ commands: string[] }initializeWorker()to return a Promise and wrappedinterrupt()inmutex.runExclusive()isInterruptedcheck - now relying on "Worker interrupted" error messageexecutedCommandsstorage from worker toruntime.tsx(survives worker termination)Core Features
✅ Web Worker-based JavaScript Runtime
eval()to execute JavaScript code in a web workerself.consolein error handlers✅ Interrupt & State Recovery
✅ UI Integration
/terminal/javascript✅ Test Coverage
Screenshots
JavaScript REPL and Editor
Security Summary
CodeQL Findings
CodeQL detected 2 code injection alerts in
public/javascript.worker.jsrelated to the use ofeval():eval(code)inrunJavaScriptfunctioneval(command)inrestoreStatefunctionSecurity Assessment: ✅ Accepted by Design
These alerts are expected and acceptable for the following reasons:
By Design: The entire purpose of this runtime is to execute user-provided JavaScript code in a REPL environment, similar to how Python's runtime executes user code with Pyodide.
Isolation: The code executes in a Web Worker, which provides isolation from the main page:
Consistent with Existing Implementation: This matches the pattern of the Python runtime, which also executes arbitrary user code (via Pyodide's
runPythonAsync).Expected Usage: Users are expected to run their own code in this environment - it's an educational/development tool, not a production code executor.
No Additional Risk: The risk profile is no different from the existing Python runtime or any other code playground/REPL tool.
Mitigations in Place:
注意点 (Implementation Notes)
self.consoleを使用して、console proxyとの無限再帰を防いでいますOriginal prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.