Skip to content

Rewrite the VS Code extension with project preview and console - #388

Merged
aspizu merged 33 commits into
mainfrom
apz/vscode-rewrite
Oct 2, 2026
Merged

aspizu merged 33 commits into
mainfrom
apz/vscode-rewrite

Conversation

@aspizu

@aspizu aspizu commented Oct 2, 2026

Copy link
Copy Markdown
Owner

Editor

  • Highlight goboscript syntax, built-in blocks, and reporters.
  • Build projects on save and show compiler errors and warnings in the Problems panel, keeping all messages for each file.
  • Replace the old build-task setup with compile-on-save.

Project preview

  • Open .sb3 files in an offline player inside VS Code.
  • Keep projects paused until the green flag is pressed. Provide stop and reload controls.
  • Preview the saved .sb3 file without rebuilding it or watching for changes. Reload reads the file again.
  • Show Scratch Addons log, warn, and error output in the project console.
  • Label messages with their sprite or Stage name, and mark clones.
  • Filter messages by level. Keep all messages across runs and reloads until Clear is clicked.

Project preview with log, warning, and error messages from a sprite, Stage, and a clone

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.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@aspizu

aspizu commented Oct 2, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-02T16:34:47.668742Z 1d8fa68 New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread editors/code/src/preview/webview/lib/project.ts
Comment thread editors/code/src/runner.ts Outdated
Comment thread editors/code/esbuild.mts
Comment thread editors/code/src/extension.ts
Comment thread editors/code/src/runner.ts Outdated
Comment on lines +54 to +57
const child = spawn("goboscript", ["build"], {
cwd: this.projectDir,
stdio: ["ignore", "pipe", "pipe"],
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Comment on lines +107 to +109
for (const [uri, diagnostics] of byUri) {
collection.set(vscode.Uri.parse(uri), diagnostics)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't care about multi-project workspaces

Comment on lines +17 to +20
vscode.window.registerCustomEditorProvider(
"goboscript.sb3Preview",
new Sb3PreviewProvider(context.extensionUri),
{ supportsMultipleEditorsPerDocument: false },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dont care

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread editors/code/src/compiler.ts
Comment on lines +23 to +24
messages.value = [
...messages.peek(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Comment thread editors/code/src/extension.ts Outdated
Comment thread editors/code/src/extension.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread editors/code/package.json
aspizu added 4 commits October 2, 2026 21:37
- 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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +39 to +41
const candidate = join(dir, name)
if (existsSync(candidate)) {
return candidate

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Comment on lines +103 to +105
timeout = setTimeout(() => {
timedOut = true
child.kill()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@aspizu
aspizu merged commit 87014c6 into main Oct 2, 2026
1 check passed
@aspizu
aspizu deleted the apz/vscode-rewrite branch October 2, 2026 16:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant