Repository navigation
Rewrite the VS Code extension with project preview and console - #388
Conversation
Replace the unused LSP client with a linter that runs `goboscript build` from PATH on save (debounced per project, nearest-ancestor project discovery) and parses the rustc-style stderr into Problems, including location-less diagnostics and `= help:` footers.
Opening a .sb3 file now shows it running in an embedded TurboWarp Scaffolding player, fully offline (with-music variant bundled via esbuild). Read-only custom editor with Reload, Green flag and Stop controls; loads the bytes on disk when opened or reloaded, never builds or watches anything. Stage is letterboxed preserving its aspect ratio, project stays paused until Green flag is pressed.
The prebuilt Scaffolding UMD marks its entry module with __esModule, so the esbuild default import was undefined; import the named Scaffolding export instead. Register message and error listeners and post "ready" before player initialization so a failure surfaces in the overlay and output channel instead of hanging on "Loading". Add a 30s load timeout and delivery/receipt logging. Toolbar buttons are now icon-only using Radix Icons (reload, play, stop) styled like native VS Code toolbar buttons, and loading state is a spinner instead of text.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d95c45cbe1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const child = spawn("goboscript", ["build"], { | ||
| cwd: this.projectDir, | ||
| stdio: ["ignore", "pipe", "pipe"], | ||
| }) |
There was a problem hiding this comment.
Preserve the last successful artifact on failed saves
Every save now runs this command directly against the project's normal output path, but src/frontend/build.rs opens and truncates <project>.sb3 before build_impl parses the source. Consequently, an ordinary syntax or type error during compile-on-save replaces the last working preview artifact with an empty or incomplete file. Build to a temporary output and replace the project artifact only after a successful compilation, or make the compiler's output write atomic.
Useful? React with 👍 / 👎.
| for (const [uri, diagnostics] of byUri) { | ||
| collection.set(vscode.Uri.parse(uri), diagnostics) | ||
| } |
There was a problem hiding this comment.
Aggregate diagnostics from projects that share a file
In a multi-root workspace where two projects report errors in the same absolute include or standard-library file, each project calls collection.set independently for that URI, so the later build overwrites the earlier project's diagnostics. A subsequent clean build of either project can also delete the other project's entries through the preceding cleanup loop. Retain diagnostics per project and publish the aggregate for each URI instead of replacing the shared collection entry.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
don't care about multi-project workspaces
| vscode.window.registerCustomEditorProvider( | ||
| "goboscript.sb3Preview", | ||
| new Sb3PreviewProvider(context.extensionUri), | ||
| { supportsMultipleEditorsPerDocument: false }, |
There was a problem hiding this comment.
Preserve console state while the preview is hidden
The custom editor is registered without retainContextWhenHidden, and the console messages exist only in the webview's in-memory signal. VS Code normally destroys a hidden webview's context, so switching to another editor tab and returning recreates the preview with an empty console, even though the feature promises to retain messages until Clear is clicked. Either retain the webview context or persist and restore the console state through the webview state API.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a98dd80871
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| messages.value = [ | ||
| ...messages.peek(), |
There was a problem hiding this comment.
Bound the project console message history
When a project logs repeatedly, such as from a forever loop, every callback copies the entire accumulated array and the console renders every retained row. The total insertion work becomes quadratic while memory and DOM usage remain unbounded, so a sufficiently chatty project can quickly freeze the preview webview. Cap the retained history or use a bounded/virtualized message buffer.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f584ea41a7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- Map spawn errors to not-found-on-path or spawn-failed failures and notify - Include spawn error detail in failure messages - Compute diagnostic ranges from file lines instead of URIs - Point launch config at aoc2024/day1 example
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1d8fa68249
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const candidate = join(dir, name) | ||
| if (existsSync(candidate)) { | ||
| return candidate |
There was a problem hiding this comment.
Return an absolute path from the compiler lookup
On Windows, when PATH contains . or another relative directory, existsSync(candidate) checks that path relative to the extension host, but the returned relative command is later spawned with cwd: projectDir. The same candidate can therefore resolve to a different goboscript.exe inside an untrusted workspace, defeating the current-directory exclusion and enabling project-supplied code execution. Resolve each PATH entry before joining the executable name and return that absolute candidate.
Useful? React with 👍 / 👎.
| timeout = setTimeout(() => { | ||
| timedOut = true | ||
| child.kill() |
There was a problem hiding this comment.
Escalate when the timed-out compiler ignores termination
When a configured compiler or wrapper traps or ignores SIGTERM on POSIX, this timeout only sends the default termination signal. Because finish is invoked only from the child's error or close events, such a process leaves inFlight true forever, never reports the timeout, and causes every subsequent save to remain queued behind it. Escalate to SIGKILL after a grace period or otherwise ensure the timed-out process is finalized.
Useful? React with 👍 / 👎.
| status.value = { kind: "error", title: "Failed to read file", detail: project.error } | ||
| return | ||
| } | ||
| await Promise.race([player.loadProject(base64ToBytes(project.value)), timeout]) |
There was a problem hiding this comment.
Prevent timed-out project loads from racing reloads
If Scaffolding takes longer than 30 seconds to load a large or malformed project, Promise.race reports a timeout but does not cancel the underlying player.loadProject call. The error state re-enables Reload, so a retry starts another load on the same player; the generation check only suppresses stale status updates and cannot prevent the first load from later mutating or replacing the retried project. Serialize loads or recreate/cancel the player before allowing a retry.
Useful? React with 👍 / 👎.
Editor
Project preview
.sb3files in an offline player inside VS Code..sb3file without rebuilding it or watching for changes. Reload reads the file again.log,warn, anderroroutput in the project console.