fix(iOS): exclude C++-guarded foreign-namespace headers from React umbrella#57575
Open
chrfalch wants to merge 1 commit into
Open
fix(iOS): exclude C++-guarded foreign-namespace headers from React umbrella#57575chrfalch wants to merge 1 commit into
chrfalch wants to merge 1 commit into
Conversation
…brella The prebuilt React-Core artifact's generated module.modulemap placed RCTFrameTimingsObserver.h in the React umbrella. That header includes <jsinspector-modern/tracing/FrameTimingSequence.h> under #ifdef __cplusplus, transitively reaching react/timing/primitives.h — a header owned by the ReactNativeHeaders_react module. The headers inventory's reachability fixpoint only follows unguarded include edges (modeling a pure-ObjC consumer), so it could not see this edge and classified the header as umbrella-safe. For Swift pods with C++ interop (e.g. react-native-unistyles), building the React clang module opens the __cplusplus guard, and primitives.h ends up owned by two modules in one compilation: C++ redefinition errors (HighResDuration, HighResTimeStamp, TraceEvent, FrameTimingSequence) and "could not build module 'React'". This broke the react-native-unistyles job in nightly-tests on 0.88.0-nightly-20260716. Fix: add a curated UMBRELLA_CXX_GUARDED_EXCLUSIONS set, checked in isUmbrellaSafe, mirroring the existing PRIVATE_REACT_HEADERS pattern, with fail-closed validation (validateUmbrellaExclusions) so a renamed or deleted entry surfaces immediately. The header still ships in React.framework/Headers and remains importable via #import <React/RCTFrameTimingsObserver.h>; it is only removed from the modular umbrella surface. Co-Authored-By: Claude Fable 5 <[email protected]>
cipolleschi
approved these changes
Jul 16, 2026
cipolleschi
left a comment
Contributor
There was a problem hiding this comment.
Thank you for fixing it
|
@cipolleschi has imported this pull request. If you are a Meta employee, you can view this in D112320697. |
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.
Summary:
The first nightly containing the prebuilt/SwiftPM stack (
0.88.0-nightly-20260716) broke thereact-native-unistylesjob in react-native-community/nightly-tests with:Root cause:
RCTFrameTimingsObserver.hincludes<jsinspector-modern/tracing/FrameTimingSequence.h>under#ifdef __cplusplus, transitively reachingreact/timing/primitives.h, which is owned by theReactNativeHeaders_reactmodule. The headers inventory's reachability fixpoint only follows unguarded include edges (modeling a pure-ObjC consumer), so it couldn't see this edge and classified the header as umbrella-safe. Swift pods with C++ interop (unistyles, Nitro-based libs) build theReactclang module as ObjC++, opening the guard — one header owned by two modules in a single compilation → C++ redefinition errors. Pure-ObjC consumers never open the guard, which is why only C++-interop libraries failed.Fix: a curated
UMBRELLA_CXX_GUARDED_EXCLUSIONSset checked inisUmbrellaSafe, mirroring the existingPRIVATE_REACT_HEADERSpattern, with fail-closed validation (validateUmbrellaExclusions, wired intoplanFromInventory) so a renamed/deleted entry surfaces immediately.The header still ships in
React.framework/Headersand stays importable via#import <React/RCTFrameTimingsObserver.h>(its only consumer today isRCTHost.mm); it is only removed from the modular umbrella surface. If a modular consumer ever needs it, it can be promoted to aPRIVATE_REACT_HEADERS.textual-style entry instead.Changelog:
[IOS] [FIXED] - Fix "redefinition of 'HighResDuration'" / "could not build module 'React'" when building Swift pods with C++ interop against the prebuilt React-Core artifact
Test Plan:
scripts/ios-prebuild/__tests__/headers-spec-test.js: the excluded header is kept out of the umbrella (fails against the previous code withReceived array: ["React/RCTFrameTimingsObserver.h"]), and exclusion drift fails closed.RCT_USE_RN_DEP=1 RCT_USE_PREBUILT_RNCORE=1).🤖 Generated with Claude Code