Skip to content

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

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

fix: Prevent exponential type re-traversal in SwiftCxxBridgedType#1387
puckey wants to merge 2 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.

puckey added 2 commits June 12, 2026 12:00
`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
…raversal

A 7-struct graph where multiple structs reference the same shared types
from many paths. Without the visited-set guard in SwiftCxxBridgedType,
nitrogen crashes with "RangeError: Maximum call stack size exceeded"
when generating the iOS autolinking bridge for this spec.
@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 Jun 12, 2026 10:22am

Request Review

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

1 participant