Fix JSG_TS_OVERRIDE macro corruption from <stdio.h> macros#6729
Merged
danlapid merged 1 commit intoMay 6, 2026
Merged
Conversation
`JSG_TS_OVERRIDE`, `JSG_TS_DEFINE`, `JSG_STRUCT_TS_OVERRIDE`, and
`JSG_STRUCT_TS_DEFINE` previously stringified their varargs via
`JSG_STRING_LITERAL`, which is a two-step "stringify after macro
expansion" helper. When a containing variadic macro forwards
`__VA_ARGS__` into the helper, the preprocessor expands any
identifiers in the argument before stringification. On Darwin,
`<stdio.h>` defines `stdin`/`stdout`/`stderr` as
`__stdinp`/`__stdoutp`/`__stderrp`, so overrides like
`{ readonly stdin: WritableStream }` were stringified as
`"{ readonly __stdinp: WritableStream }"`, corrupting the generated
TypeScript on macOS builds.
Stringify directly with `#__VA_ARGS__` at the outermost macro that
captures the user's tokens. Document the hazard on `JSG_STRING_LITERAL`
and add a regression test in `rtti-test.c++`.
|
All contributors have signed the CLA ✍️ ✅ |
Member
Author
|
I have read the CLA Document and I hereby sign the CLA |
Member
|
Damn it. This is the exact problem I was puzzled by last week. Nice catch! |
npaun
approved these changes
May 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The
JSG_TS_OVERRIDE,JSG_TS_DEFINE,JSG_STRUCT_TS_OVERRIDE, andJSG_STRUCT_TS_DEFINEmacros stringify their varargs viaJSG_STRING_LITERAL, a two-step helper that expands macro identifiers in the argument before stringification.On Darwin,
<stdio.h>definesstdin,stdout, andstderras preprocessor macros (__stdinp,__stdoutp,__stderrp). Override blocks containing those identifiers are silently corrupted in the stringified TypeScript:This is observable in
src/workerd/api/container.h, where theExecOptionsandExecProcessoverrides reference these names. The platform divergence breaksbazel run //typesfor downstream consumers building on macOS — the generatedworker-configuration.d.tsdiffers from the Linux-built committed snapshot.Fix
Stringify directly with
#__VA_ARGS__at the outermost macro that captures the user's tokens, rather than forwarding throughJSG_STRING_LITERAL. Single-step stringification doesn't trigger preprocessor expansion of the argument tokens.JSG_STRING_LITERALis preserved inmacro-meta.h(it is still used byedgeworker/server/async-signal-debug.hfor variable-name logging where two-step semantics are harmless). Its doc comment now warns against using it for user-supplied source-code blocks and points readers at the correct pattern.Testing
Added a regression test (
KJ_TEST("typescript macros with stdio identifiers")inrtti-test.c++) that asserts override and define blocks containingstdin/stdout/stderrsurvive stringification verbatim. Verified on macOS that:bazel test //src/workerd/jsg:all— 46/46 pass.bazel build //types— generated experimental and latest types match the committed Linux snapshot exactly (diff -r types/generated-snapshot/ bazel-bin/types/definitions/is empty).