Skip to content

Offer protoc's language targets alongside protobuf-net's - #3

Merged
mgravell merged 1 commit into
mainfrom
protoc-languages
Aug 24, 2026
Merged

mgravell merged 1 commit into
mainfrom
protoc-languages

Conversation

@mgravell

Copy link
Copy Markdown
Member

The old ASP.NET site generated C++, Java, Objective-C, PHP, Python and Ruby by shelling out to protoc. The static rewrite dropped them: protoc is a native executable, and there is still no maintained WebAssembly build of the compiler — only of the runtime. This brings them back through protoc.protobuf-net.dev, a Cloudflare Worker in front of a container that runs the real thing, plus Kotlin and Google's own C# generator.

That service is a separate repo, and this PR only knows two things about it: the URL, and the response shape.

What this changes

The language picker gains a second group. Values are namespaced (protoc:csharp) because protoc has a csharp generator too — and that one is worth having, since Google.Protobuf output is a genuinely different answer to the same question as the C# above it.

Nothing is sent while typing. Choosing a protoc target generates once, because choosing it is the decision to use it; after that, editing marks the output stale and it is re-sent only on Generate. Debounced keystrokes are fine for a generator running in your own tab and rude for one running on a server, and "my schema is uploaded as I type" is not a promise to make on someone's behalf.

The header badge and the footer now say which of the two modes is in play. "Runs locally" was true of everything here until now, and shouldn't quietly stop being true while a schema is being posted somewhere.

The service replies with the same GenerateResponse shape the WebAssembly path returns, so both go through one applyResponse: same output pane, tabs, message list and editor gutter. Diagnostics raised against an imported file are shown in the message list but not projected onto the editor, since their line numbers point into a file that is not on screen.

Imports need no plumbing on this side: the service carries the same .proto corpus protobuf-net.Reflection embeds, so google/** and protobuf-net/** resolve identically either way. Its include path puts protoc's own well-known types ahead of that corpus, so the generators keep the descriptor.proto they were built against.

Cost

Output highlighting reuses the legacy modes already bundled for C# — clike covers C++, Java, Kotlin and Objective-C — plus python and ruby: +14 kB raw, +5 kB gzipped (391.40 → 405.72 kB; 128.12 → 133.12 kB), against a ~1.7 MB WebAssembly payload.

PHP output is not highlighted. @codemirror/legacy-modes has no PHP mode, and @codemirror/lang-php brings the HTML, CSS and JavaScript parsers with it to colour output that is read once and copied.

Checked

tsc --noEmit, vitest (27 pass, 8 new covering the value round-trip and the response reader — including replies that are not the service at all), vite build. The service's own suite passes against a real protoc in the image.

Not checked in a browser: no automation to hand here, and wrangler dev needs Node 22. Worth clicking through each target once the service is deployed and DNS is live.

The old ASP.NET site generated C++, Java, Objective-C, PHP, Python and Ruby by
shelling out to protoc; the static rewrite dropped them, because protoc is a
native executable and there is no maintained WebAssembly build of the compiler.
This brings them back through protoc.protobuf-net.dev, a Cloudflare Worker in
front of a container that runs the real thing - plus Kotlin and Google's own C#
generator, which is a genuinely different answer to the same question as the C#
sitting above it in the picker.

The language picker now has two groups, and the values are namespaced
(protoc:csharp) because protoc has a csharp generator too. Choosing a protoc
target generates once - choosing it is the decision to use it - and after that
editing marks the output stale rather than posting every keystroke to somebody
else's server. The header badge and the footer say which of the two is in play;
"runs locally" was true of everything here until now and should not quietly
stop being true.

The service answers with the same GenerateResponse shape the WebAssembly path
returns, so both paths share applyResponse: one code path for output, tabs,
diagnostics and the editor gutter. Diagnostics against an imported file are
shown but not projected onto the editor, since their line numbers point into a
file that is not on screen.

Imports need no plumbing here: the service carries the same .proto corpus that
protobuf-net.Reflection embeds, so google/** and protobuf-net/** resolve the
same way on both paths.

Output highlighting reuses the legacy modes already present for C# - clike
covers C++, Java, Kotlin and Objective-C - plus python and ruby, which is
+14 kB raw and +5 kB gzipped on the bundle. PHP gets no tokenizer: legacy-modes
has no PHP mode and lang-php would drag in the HTML, CSS and JavaScript parsers
to colour output that is read once and copied.
@mgravell
mgravell merged commit 855cdf0 into main Aug 24, 2026
2 checks passed
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