Skip to content

Commit b94402a

Browse files
chrfalchclaude
andcommitted
fix(iOS): make jsinspector-modern tracing state types move-only for Swift C++ interop
TraceRecordingState and HostTracingProfile hold std::vector<> of move-only types (RuntimeSamplingProfile, FrameTimingSequence). Their implicit copy constructors are declared but ill-formed on instantiation. Plain C++ never instantiates them, but a Swift target using -cxx-interoperability-mode=default (any Nitro-based library) imports these types via the prebuilt clang modules and its generated bridging uses them as copyable Swift values, forcing instantiation of the ill-formed copy ctor — a hard error on Xcode 26.3 that kills every Swift file in the consumer (e.g. react-native-unistyles in nightly-tests). Declare the types explicitly move-only. Swift then imports them as non-copyable; it is also more correct C++ (these types were never copyable). HostTracingProfile is no longer an aggregate, so its one designated-initializer site is converted to member assignment. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent e640278 commit b94402a

3 files changed

Lines changed: 32 additions & 7 deletions

File tree

packages/react-native/ReactCommon/jsinspector-modern/HostTargetTraceRecording.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,16 @@ tracing::HostTracingProfile HostTargetTraceRecording::stop() {
6464
auto startTime = *startTime_;
6565
startTime_.reset();
6666

67-
return tracing::HostTracingProfile{
68-
.processId = oscompat::getCurrentProcessId(),
69-
.startTime = startTime,
70-
.frameTimings = frameTimings_.pruneExpiredAndExtract(),
71-
.instanceTracingProfiles = std::move(state.instanceTracingProfiles),
72-
.runtimeSamplingProfiles = std::move(state.runtimeSamplingProfiles),
73-
};
67+
// Member-wise assignment instead of designated initializers:
68+
// HostTracingProfile declares its special members (move-only) and is no
69+
// longer an aggregate.
70+
tracing::HostTracingProfile profile;
71+
profile.processId = oscompat::getCurrentProcessId();
72+
profile.startTime = startTime;
73+
profile.frameTimings = frameTimings_.pruneExpiredAndExtract();
74+
profile.instanceTracingProfiles = std::move(state.instanceTracingProfiles);
75+
profile.runtimeSamplingProfiles = std::move(state.runtimeSamplingProfiles);
76+
return profile;
7477
}
7578

7679
void HostTargetTraceRecording::recordFrameTimings(

packages/react-native/ReactCommon/jsinspector-modern/tracing/HostTracingProfile.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@ namespace facebook::react::jsinspector_modern::tracing {
2323
* messages.
2424
*/
2525
struct HostTracingProfile {
26+
HostTracingProfile() = default;
27+
28+
// Explicitly move-only: FrameTimingSequence and RuntimeSamplingProfile are
29+
// not copyable, so the implicit copy constructor is ill-formed the moment it
30+
// is instantiated. Plain C++ never instantiates it, but Swift's C++ interop
31+
// does when these headers are reached from an imported module, turning it
32+
// into a hard compile error (Xcode 26.3).
33+
HostTracingProfile(const HostTracingProfile &) = delete;
34+
HostTracingProfile &operator=(const HostTracingProfile &) = delete;
35+
HostTracingProfile(HostTracingProfile &&) = default;
36+
HostTracingProfile &operator=(HostTracingProfile &&) = default;
37+
2638
// The ID of the OS-level process that this Trace Recording is associated
2739
// with.
2840
ProcessId processId;

packages/react-native/ReactCommon/jsinspector-modern/tracing/TraceRecordingState.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ struct TraceRecordingState {
3131
{
3232
}
3333

34+
// Explicitly move-only: RuntimeSamplingProfile is not copyable, so the
35+
// implicit copy constructor is ill-formed the moment it is instantiated.
36+
// Plain C++ never instantiates it, but Swift's C++ interop (ClangImporter)
37+
// does when a consumer imports these headers as part of a module, turning
38+
// it into a hard compile error (Xcode 26.3).
39+
TraceRecordingState(const TraceRecordingState &) = delete;
40+
TraceRecordingState &operator=(const TraceRecordingState &) = delete;
41+
TraceRecordingState(TraceRecordingState &&) = default;
42+
TraceRecordingState &operator=(TraceRecordingState &&) = default;
43+
3444
// The mode of this Trace Recording.
3545
tracing::Mode mode;
3646

0 commit comments

Comments
 (0)