Skip to content

Commit 329b4c4

Browse files
huntiemeta-codesync[bot]
authored andcommitted
Resolve initiator for WebSocket CDP events
Summary: **Context** This stack implements WebSocket event debugging for the Network panel in React Native DevTools. **This diff** Wire up request initiator logic for `WebSocket` on the JS side, completing functionality for WebSocket network debugging. Mirrors the HTTP pipeline's `unstable_devToolsRequestId` plumbing. **Changes** - Wire up `unstable_devToolsRequestId` plumbing through `Libraries/WebSocket/WebSocket.js` and `NativeWebSocketModule`. - Adds `testWebSocketCreatedWithInitiator`, asserting the initiator stack (function name, line number, source URL) resolves through `Network.webSocketCreated`. Changelog: [Internal] Differential Revision: D111561995
1 parent 7d7226f commit 329b4c4

5 files changed

Lines changed: 88 additions & 4 deletions

File tree

packages/react-native/Libraries/WebSocket/WebSocket.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,14 @@ class WebSocket extends EventTarget {
145145
);
146146
this._socketId = nextWebSocketId++;
147147
this._registerEvents();
148-
NativeWebSocketModule.connect(url, protocols, {headers}, this._socketId);
148+
const devToolsRequestId =
149+
global.__NETWORK_REPORTER__?.createDevToolsRequestId();
150+
NativeWebSocketModule.connect(
151+
url,
152+
protocols,
153+
{headers, unstable_devToolsRequestId: devToolsRequestId},
154+
this._socketId,
155+
);
149156
}
150157

151158
get binaryType(): ?BinaryType {

packages/react-native/React/CoreModules/RCTWebSocketModule.mm

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,10 @@ - (void)invalidate
152152
[webSocket setDelegateDispatchQueue:[self methodQueue]];
153153
webSocket.delegate = self;
154154
webSocket.reactTag = @(socketID);
155-
webSocket.inspectorRequestId = [[NSUUID UUID] UUIDString];
155+
// Prefer the DevTools request ID created by the JS caller, which carries the
156+
// request initiator stack trace for CDP reporting.
157+
NSString *devToolsRequestId = options.unstable_devToolsRequestId();
158+
webSocket.inspectorRequestId = devToolsRequestId.length > 0 ? devToolsRequestId : [[NSUUID UUID] UUIDString];
156159
if (!_sockets) {
157160
_sockets = [NSMutableDictionary new];
158161
}

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,18 @@ public class WebSocketModule(context: ReactApplicationContext) :
168168
val request = builder.build()
169169

170170
if (isInspectorNetworkReportingEnabled()) {
171-
val requestId = UUID.randomUUID().toString()
171+
// Prefer the DevTools request ID created by the JS caller, which carries
172+
// the request initiator stack trace for CDP reporting.
173+
val devToolsRequestId =
174+
if (
175+
options?.hasKey("unstable_devToolsRequestId") == true &&
176+
options.getType("unstable_devToolsRequestId") == ReadableType.String
177+
) {
178+
options.getString("unstable_devToolsRequestId")
179+
} else {
180+
null
181+
}
182+
val requestId = devToolsRequestId ?: UUID.randomUUID().toString()
172183
inspectorRequestIds[id] = requestId
173184
InspectorNetworkReporter.reportWebSocketCreated(requestId, url)
174185
InspectorNetworkReporter.reportWebSocketWillSendHandshakeRequest(

packages/react-native/ReactCommon/jsinspector-modern/tests/NetworkReporterTest.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,66 @@ TEST_P(NetworkReporterTest, testCompleteWebSocketFlow) {
572572
})");
573573
}
574574

575+
TEST_P(NetworkReporterTest, testWebSocketCreatedWithInitiator) {
576+
InSequence s;
577+
578+
this->expectMessageFromPage(JsonEq(R"({
579+
"id": 0,
580+
"result": {}
581+
})"));
582+
this->toPage_->sendMessage(R"({
583+
"id": 0,
584+
"method": "Debugger.enable"
585+
})");
586+
587+
this->expectMessageFromPage(JsonEq(R"({
588+
"id": 1,
589+
"result": {}
590+
})"));
591+
this->toPage_->sendMessage(R"({
592+
"id": 1,
593+
"method": "Network.enable"
594+
})");
595+
596+
auto& runtime = engineAdapter_->getRuntime();
597+
598+
auto requestId = this->eval(R"( // line 0
599+
function openSocket() { // line 1
600+
return globalThis.__NETWORK_REPORTER__.createDevToolsRequestId(); // line 2
601+
} // line 3
602+
openSocket(); // line 4
603+
604+
//# sourceURL=webSocketInitiatorTest.js
605+
)")
606+
.asString(runtime)
607+
.utf8(runtime);
608+
609+
this->expectMessageFromPage(JsonParsed(AllOf(
610+
AtJsonPtr("/method", "Network.webSocketCreated"),
611+
AtJsonPtr("/params/requestId", requestId),
612+
AtJsonPtr("/params/url", "wss://example.com/initiator"),
613+
AtJsonPtr("/params/initiator/type", "script"),
614+
AtJsonPtr(
615+
"/params/initiator/stack/callFrames",
616+
AllOf(
617+
Each(AtJsonPtr("/url", "webSocketInitiatorTest.js")),
618+
Contains(AllOf(
619+
AtJsonPtr("/functionName", "openSocket"),
620+
AtJsonPtr("/lineNumber", 2))))))));
621+
622+
NetworkReporter::getInstance().reportWebSocketCreated(
623+
requestId, "wss://example.com/initiator");
624+
625+
this->expectMessageFromPage(JsonEq(R"({
626+
"id": 2,
627+
"result": {}
628+
})"));
629+
this->toPage_->sendMessage(R"({
630+
"id": 2,
631+
"method": "Network.disable"
632+
})");
633+
}
634+
575635
TEST_P(NetworkReporterTest, testNetworkEventsWhenDisabled) {
576636
EXPECT_FALSE(NetworkReporter::getInstance().isDebuggingEnabled());
577637

packages/react-native/src/private/specs_DEPRECATED/modules/NativeWebSocketModule.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ export interface Spec extends TurboModule {
1616
readonly connect: (
1717
url: string,
1818
protocols: ?Array<string>,
19-
options: {headers?: Object},
19+
options: {
20+
headers?: Object,
21+
unstable_devToolsRequestId?: string,
22+
},
2023
socketID: number,
2124
) => void;
2225
readonly send: (message: string, forSocketID: number) => void;

0 commit comments

Comments
 (0)