fix: indent standalone blocks in tseynit - #2933
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes indentation behavior in the tseynit AST-to-JS stringifier so that standalone/nested blocks respect the caller-provided indentation, while control-flow statements (if/else/for/while/for-of) still keep their bodies directly after the control syntax.
Changes:
- Indent block opening braces using the provided indentation (fixes standalone/nested blocks starting at column 0).
- Ensure control-flow bodies don’t gain extra leading indentation by trimming the stringified body prefix.
- Add a targeted regression test and update affected obfuscation inline snapshots.
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| packages/typegpu/src/shared/tseynit.ts | Adjusts stringifyStatement block formatting and control-flow body rendering to preserve correct indentation. |
| packages/typegpu/tests/internal/tseynit.test.ts | Adds a focused regression test covering standalone nested blocks + control-flow formatting expectations. |
| packages/unplugin-typegpu/test/obfuscation.test.ts | Updates obfuscation snapshots to match the corrected block indentation output. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
tseynit.ts— indent block opening braces.NODE.blocknow emits${ident}{\n…\n${ident}}, so standalone blocks inherit the caller's indentation instead of starting at column 0.- Control-flow bodies trimmed.
if/else,for,while, andfor-ofbodies call.trimStart()so the block{still hugs the)— exactly the double-space failure mode the issue (#2894) flagged. - Regression + snapshot updates. New
tseynit.test.tscase pins both cases (indented standalone block, inlineif-body); the obfuscation snapshots reflect only the corrected{indent.
The fix matches the issue intent precisely, and the trimmed blast radius is worth noting: stringifyNode output feeds only error-message text (wgslGenerator.ts) and test snapshots — never emitted WGSL — so this is a formatting-only correction. I verified .trimStart() is safe across every statement type (each stringifies to a first line prefixed by exactly the indent), and nested standalone blocks inside a control-flow body still indent correctly.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
|
Can we do this without trim? |
|
Implemented without trimming in
Focused verification: |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
- Replaced
.trimStart()with a threadedomitInitialIndentparameter.stringifyStatementnow takes a third argument and every statement type (expression,block,return,let,const,continue,break) returns via aninitialIndentthat is elided only for control-flow bodies (if/else,for,while,forOf). This is behaviorally byte-identical to the previously-approved.trimStart()version — thetseynitregression test and the obfuscation snapshots are unchanged in this commit. - Cleaner than trimming. Omitting the caller-owned indent at the source instead of post-hoc
.trimStart()means the stringifier never strips whitespace it didn't itself add, which is more robust against future formatter-owned or semantic leading space. - Verified against the regression case. Traced
if (true) { [3, 4]; }and the standalone nested{ [1, 2]; }block through the new code path: the{of a control-flow body hugs the)(no double space), while the standalone block opens indented and closes atident. The inline snapshot matches exactly.
The refactor preserves the prior fix precisely while removing the whitespace-trim bluntness the earlier version carried.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

Summary
if/else/for/while/for-oftrimStart, so the stringifier never removes semantic or future formatter-owned whitespaceCloses #2894.
Verification
tseynitsuite: 29/29 passedunplugin-typegpuobfuscation suite: 24/24 passedgit diff --checkpassed