Skip to content

fix: Prevent exponential type re-traversal in SwiftCxxBridgedType#1387

Open
puckey wants to merge 3 commits into
mrousavy:mainfrom
puckey:fix/swift-exponential-traversal
Open

fix: Prevent exponential type re-traversal in SwiftCxxBridgedType#1387
puckey wants to merge 3 commits into
mrousavy:mainfrom
puckey:fix/swift-exponential-traversal

Conversation

@puckey

@puckey puckey commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

#1247 fixed the Maximum call stack size exceeded crash in nitrogen by adding a visited set to KotlinCxxBridgedType — but the same unguarded recursion exists in SwiftCxxBridgedType, the class that generates the Swift ↔ C++ bridge. getRequiredImports() and getExtraFiles() re-traverse shared types from every path in the type graph, so for specs with many interconnected structs, nitrogen still crashes on current main while generating the iOS autolinking bridge:

❌  Failed to generate spec for TestObjectSwiftKotlin! RangeError: Maximum call stack size exceeded
    at SwiftCxxBridgedType.getRequiredBridge (.../syntax/swift/SwiftCxxBridgedType.js:102:16)
    at .../autolinking/ios/createSwiftCxxBridge.js:21:27

This PR applies the same per-call-tree visited-set guard to SwiftCxxBridgedType. The actual fix is one file (+15/−5); everything else is the regression test and its generated output.

Fixes #1079.

Real-world impact: react-native-iap currently works around this by raising Node's stack size to 64 MB (commit), and react-native-audio-browser ships a vendored patched build of nitrogen just to work around the same crash.

Test plan

  • Added a 7-struct Gallery graph to the test specs, where multiple structs reference the same shared types from many paths (the shape that triggers the exponential blowup)
  • On current main, bun run specs crashes with RangeError: Maximum call stack size exceeded
  • With this fix, all 7/7 HybridObjects generate in ~0.3s
  • Regenerating produces zero diff against the committed generated files; tsc and eslint pass

Extracted from #1232 so the crash fix can land independently of the cyclic-struct discussion there.

@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
nitro-docs Skipped Skipped Jul 1, 2026 7:25am

Request Review

@mrousavy

Copy link
Copy Markdown
Owner

Hey - sorry for leaving this PR sitting for a while, it was a bit hard to review and I focused primarily on VisionCamera.

Is this still an issue? If yes, we should rebase it with latest main

@puckey puckey force-pushed the fix/swift-exponential-traversal branch from 0f36d96 to 5e7146b Compare June 30, 2026 08:56
@puckey puckey force-pushed the fix/swift-exponential-traversal branch from 5e7146b to b571aaa Compare June 30, 2026 09:01
@puckey

puckey commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

@mrousavy Yes, still an issue. On the latest main (0.36.0), the test spec still crashes codegen with Maximum call stack size exceeded until the fix is applied.

To make review easier I've rebased onto main and split it into three commits:

  1. puckey/nitro@12756ea: failing test
  2. puckey/nitro@60fc9f8: the fix
  3. puckey/nitro@b571aaa: working codegen after fix

puckey added 3 commits July 1, 2026 09:24
…raversal

A 7-struct graph where multiple structs reference the same shared types
from many paths, plus a `bounceGallery` method on the test HybridObjects
to exercise it. Without the visited-set guard in SwiftCxxBridgedType,
nitrogen crashes with "RangeError: Maximum call stack size exceeded" while
generating the iOS autolinking bridge for this spec, before any code can
be generated.
`getRequiredImports()` and `getExtraFiles()` in nitrogen's
`SwiftCxxBridgedType` (the TypeScript class that generates the
Swift <-> C++ bridge code) have no protection against re-traversing
the same type from multiple paths in the type graph, causing
exponential blowup and a "Maximum call stack size exceeded" crash
for projects with many interconnected struct types.

mrousavy#1247 added a visited-set guard to the equivalent
`KotlinCxxBridgedType`; this applies the same per-call-tree
visited-set guard to `SwiftCxxBridgedType`, which still crashes
on large specs.

Fixes mrousavy#1079
Generated output for the Gallery struct graph, produced by `bun run specs`
with the SwiftCxxBridgedType fix in place. Mechanical codegen — verifiable
by re-running nitrogen, which yields a zero diff.
@puckey puckey force-pushed the fix/swift-exponential-traversal branch from b571aaa to 1f62f96 Compare July 1, 2026 07:25
@puckey

puckey commented Jul 1, 2026

Copy link
Copy Markdown
Contributor Author

rebased on latest main again for 0.36.1

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.

maximum call stack error after upgrade 0.31.10

2 participants