Skip to content

Add standalone TypeScript 7 playground - #3653

Draft
Jake Bailey (jakebailey) wants to merge 75 commits into
microsoft:v2from
jakebailey:ts7-playground
Draft

Jake Bailey (jakebailey) wants to merge 75 commits into
microsoft:v2from
jakebailey:ts7-playground

Conversation

@jakebailey

Copy link
Copy Markdown
Member

prototypin

Build a static Monaco 0.56 playground against the local wasip1 compiler API. Support Twoslash type queries, diagnostics, JavaScript emit, standard library types, and a browser console API without playground plugins.
Add the /play/7-1/ Gatsby route and materialize the standalone bundle as ignored static assets during site start and production builds.
Make the playground deployable from a standalone website checkout by committing the wasip1 API packages, standard libraries, WASM module, version metadata, and legal notices. Brand the route as /play/7/.
Force-add the generated API package output and wasip1 module because the website's global dist ignore otherwise omits the files required by a fresh checkout.
@jakebailey Jake Bailey (jakebailey) added the deploy-preview Enables automatic deployments to preview environments on a PR label Sep 16, 2026
Port the browser WASI and Monaco LSP transport from the 2026 GopherCon talk. Serve the playground directly at /play/7/ so its service worker can establish cross-origin isolation for SharedArrayBuffer.

Keep the synchronous compiler API authoritative for diagnostics, Twoslash, emit, and window.ts while LSP provides completion, hover, signature help, navigation, references, rename, and related editor features.
Set an explicit /play/7/ base in production so Azure's slashless /play/7 route resolves scripts, styles, workers, libraries, and the service worker from the playground directory.
Canonicalize Azure's slashless /play/7 URL before the scoped cross-origin isolation service worker starts. This lets the worker control /play/7/ after its activation reload without repeatedly registering.
Add a virtual project with editable tsconfig.json and multiple source files. Drive native compilation from the config and show all emitted files together in a highlighted, non-Monaco output pane.

Restore Run with captured CommonJS console output and reuse the existing playground loading grid while the compiler API and LSP initialize.
Add a collapsible file tree with nested file creation and default to src/index.ts. Persist the complete project and active file in an old-playground-style compressed #code URL.

Enable declaration emit by default, trim display-only trailing newlines, remove Twoslash and WebAssembly branding, and provide local JSON Schema completion, hover, and validation for tsconfig.json and jsconfig.json.
Ignore trailing commas and suppress SchemaStore enum diagnostics when TypeScript accepts the value with different casing. Migrate projects saved before the src directory change so their config includes the moved files and enables declaration emit.
Stream the compiler, libraries, and config schema with real byte progress. Show WebAssembly compilation as indeterminate, report library mounting by file count, and finish with the actual LSP startup stages.

Reuse the downloaded libraries in the LSP worker, add a Reset control for non-emitting saved projects, and explicitly route Ctrl/Cmd-click through go to definition.
Store the compiler WASM, library bundle, and config schema in a content-versioned browser cache. Refreshes now read those artifacts locally and new compiler artifacts automatically use a new cache namespace.

Remove the implementation-detail message about WebAssembly compile progress while keeping that phase honestly indeterminate.
Enable Monaco semantic highlighting and add explicit theme colors for TypeScript semantic token kinds. Recognize bundled library URIs so definitions such as console.log open the read-only lib.dom.d.ts model.
Replace the full-screen loading blocker with a compact translucent progress card. Keep the file tree, Monaco editor, emit pane, and Run output visible and editable throughout compiler and LSP startup.
Widen the explorer slightly and add vertical hierarchy guides, branch connectors, stronger folder rows, and consistent per-level indentation.
Register the ^? inlay provider for JavaScript and build a supplemental allowJs program for source models outside the configured project. This matches LSP inferred-project hover behavior without changing tsconfig-driven emit.
Update the playground to the current wasip1 compiler, JavaScript API client, standard libraries, and legal notices. Adapt createProgram calls to the new API signature and normalize bundled library definition URIs for Monaco navigation.
Add an in-page compiler selector for Native 7.1, classic stable releases, Nightly, and custom or PR CDN build IDs. Run classic compilers in a dedicated worker with project emit, diagnostics, hover, completion, definitions, references, signature help, Run, and type queries.

Accept old ?ts= and #code/ URLs, migrate @filename multi-file sources and legacy compiler-option parameters, preserve project state while switching backends, and add a Native 7.1 handoff to the classic playground version menu.
Comment thread packages/playground-v2/src/strada.worker.ts Fixed
Stack the file browser, editor, and output at phone widths so the workspace remains usable without horizontal page scrolling.

Add a collapsible file browser, touch-sized controls, safe-area spacing, and landscape handling.
Make definition jumps reversible so users can inspect project or bundled declarations without losing their previous editor location.

Expose Back and Forward controls and label bundled library files clearly.
Provide an explicit Delete action for the active project file while keeping bundled declarations protected and ensuring the project always retains a fallback file.

Reload after deletion so the WASI language server is rebuilt without stale files from its startup filesystem.
Selecting a classic TypeScript release should not remove the language-service features users expect from the existing playground.

Port Monaco's TypeScript adapters across the Strada worker boundary for rename, formatting, symbols, highlights, quick fixes, inlay hints, and richer completions, with compatibility fallbacks for older compiler APIs.
Inline markers and a toolbar count are not enough when a project has multiple files or configuration diagnostics.

Show a severity-sorted Problems list with file locations and direct navigation for both Native and Strada diagnostics.
Package imports should provide diagnostics, completion, and definition navigation without requiring users to manually copy declaration files into the project.

Reuse the website's existing ATA implementation, cache downloaded declarations, mount them into Native and Strada, and restart Native only when its immutable LSP filesystem needs newly acquired files.
A replacement playground should retain the existing learning entry points without depending on generated website files that are absent from clean package builds.

Bundle the example catalog, load examples as real projects with their compiler settings, and provide responsive help topics written for the unified workspace.
The TS7 playground package must build before repository bootstrap and without generated workspace package outputs.

Bundle the existing ATA runtime, declarations, package metadata, and license with the other static playground dependencies.
Examples and help add useful toolbar actions, but the desktop row can exceed the available width before the phone layout activates.

Allow the toolbar actions to wrap independently while retaining the tablet workspace columns.
The new playground is no longer specific to one compiler release, so its package and product identity should describe the long-term replacement rather than the initial TypeScript 7 implementation.
The replacement playground needs a product-oriented URL instead of one tied to the compiler version that introduced it. Keep the previous route as a lightweight redirect so existing links retain their query and project hash.
}

async function initialize(args: InitMessage["args"]) {
ts = new Function(`${args.compilerSource}\nreturn ts;`)() as TS

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is unavoidable until we do some sort of CDN stuff

The compact site links and custom editor theme did not consistently meet AA contrast and touch-target requirements. Use accessible menu and syntax colors while preserving clear selections and inlay hints in both themes.
The playground depended on an opaque binary package copied from a conference talk, making its Monaco patches difficult to review, reproduce, or upstream. Keep the patched source and its provenance in the workspace and rebuild it with the repository toolchain before Playground v2.
Comment thread packages/monaco-lsp-client/src/adapters/LspCapabilitiesRegistry.ts Fixed
Comment thread packages/monaco-lsp-client/src/adapters/LspCapabilitiesRegistry.ts Fixed
The LSP client is used only while building the private website, so carrying its full unpublished source in this repository is unnecessary. Pin Monaco 0.56.0 exactly and keep only the Playground-specific changes as a pnpm patch that esbuild consumes directly.
Some Monaco models are read-only projections of documents already owned by the language server. Expose generic synchronization and diagnostics policies in the patched client, and keep TypeScript library path knowledge in Playground v2 rather than the Monaco integration.
Playground v2 needs the current Corsa API, WASI runtime, and standard libraries from the wasip1 branch. Follow the WASI package's new lib/tsc.wasm layout and record the exact source revision so future artifact refreshes remain traceable.
The refreshed API imports newly generated filesystem, AST, and enum modules. The repository-wide dist ignore hid those files from the initial compiler refresh, so explicitly track vendored compiler distributions and include the complete module graph.
Automatic type acquisition treated Node subpaths as npm packages and mounted the runtime package metadata instead of the matching DefinitelyTyped package. Keep Node subpaths on @types/node, mount declaration package metadata, and include acquired ambient type packages in the effective compiler configuration.
Single-line ellipsis and button selection behavior hid diagnostic details and made copying an entire problem unreliable. Wrap complete messages and preserve text selections instead of navigating when a user drags across a problem.
Acquired ambient packages affect compilation even when the visible TSConfig omits compilerOptions.types. Surface that implicit configuration in TSConfig CodeLens and the effective-config view while preserving an explicitly configured types list.
The legacy ATA design ties acquisition to Strada preprocessing and
incremental callback state. Playground v2 needs compiler-backed discovery,
project acquisition policy, and complete snapshots that can remove stale
typings without restarting the page.

Keep the new engine isolated so it can evolve independently before any
changes are brought back to the old public ATA package.
Playground v2 now owns an independent acquisition engine, so the earlier
shared ATA fixes are no longer needed on this branch. Keep the public
package unchanged relative to v2 until improvements are deliberately
brought back.
Playground v2 should remain separate from the existing playground. Remove
the version-menu handoff so the legacy entry point matches v2.
Use the new playground for ordinary site and shared-code links while
keeping the legacy editor available for plugins and existing workflows.

Preserve previous v2 URLs and cached compiler downloads so the move
does not discard shared projects or require another large download.
Comment thread packages/playground-v2/scripts/smoke-test.mjs Fixed
Generated plugin projects need installation and development links that
still reach the plugin-capable playground after the route migration.
Parsing generated redirect HTML adds no coverage and incorrectly looks
like HTML sanitization to CodeQL. Keep the redirect behavior covered
without introducing a tag-matching regular expression.
The compiler and language server should be usable independently of
package CDN latency. Waiting for declarations hid already available
emit, while metadata resolution and compiler updates obscured progress.

Expose pending package work without blocking the editor, and keep early
missing-type diagnostics from requesting stale historical code fixes.
Acquired declarations already reached the compiler and language server,
but unchanged source models retained their initial missing-package
markers. Refresh diagnostic reports when dependencies or effective
options change, and discard reports from superseded requests.
The native editor receives diagnostic reports from the language server.
Publishing the same reports from the compiler API produced duplicate
hover messages. Keep API output for Problems and local configuration
annotations, while preserving Strada's editor diagnostics.
Keep scarce editor space focused on the current file, with a way back
when navigation leaves the project. Project reset belongs with the
primary actions rather than file management.

Pane-local controls, consistent disclosure rows, and expandable help
make the interface easier to scan without removing useful settings.
Synchronous compiler runs and declaration parsing interrupted typing
for hundreds of milliseconds. Keep automatic emit, checking, and type
queries in a worker while preserving the synchronous window.ts API.

Reuse compiler snapshots and declaration discovery, coalesce queued
compilations, and yield while synchronizing acquired editor models so
background updates do not create another input-blocking burst.
Automatic compilation already runs in workers, so the native page's
compiler instance and filesystem mirror existed only for console use.
Drop that extra WASM instance and keep compiler APIs internal.
Whole-project diagnostics remain necessary even when Monaco requests
reports only for individual documents. Reuse snapshot configuration
and avoid preparing orphan programs when there are no type queries,
without reducing the scope of project checking.
Typing and cursor events often saved the same project multiple times.
Combine those updates and skip unchanged storage and URL writes while
preserving pending edits across navigation and immediate reloads.
Use the committed compiler build with the reactor host owned by the
TypeScript API package. Keep its binary, library index, declarations,
and configuration schemas paired with the matching implementation.

Refresh from fa49b4514d79a1121c9e20fb7796412233f8fd25 and consume the
artifact package's library index instead of maintaining a separate
copy of the standard libraries.
@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

Azure Static Web Apps: Your stage site is ready! Visit it here: https://victorious-plant-05c166c10-3653.centralus.5.azurestaticapps.net

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

deploy-preview Enables automatic deployments to preview environments on a PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants