Skip to content

Commit 2bcb3e1

Browse files
huntiemeta-codesync[bot]
authored andcommitted
Add unstable_fastRefreshComplete CDP event (facebook#56273)
Summary: Pull Request resolved: facebook#56273 Adds a new, experimental `ReactNativeApplication.unstable_fastRefreshComplete` CDP event, emitted to subscribed active CDP sessions when a Fast Refresh update completes. **Notes** - As with D97486551, we reuse the `changeId` block in `HMRClient.js`, ensuring duplicate updates for the same change are not reported. Changelog: [Internal] Reviewed By: GijsWeterings, hoxyq Differential Revision: D98493216 fbshipit-source-id: b0b81a210fb84873e9358aa5484038062f110103
1 parent 22d3275 commit 2bcb3e1

File tree

5 files changed

+87
-9
lines changed

5 files changed

+87
-9
lines changed

packages/react-native/Libraries/Utilities/HMRClient.js

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -237,15 +237,7 @@ Error: ${e.message}`;
237237
const changeId = body?.changeId;
238238
if (changeId != null && changeId !== lastMarkerChangeId) {
239239
lastMarkerChangeId = changeId;
240-
performance.mark('Fast Refresh - Update done', {
241-
detail: {
242-
devtools: {
243-
dataType: 'marker',
244-
color: 'primary',
245-
tooltipText: 'Fast Refresh \u269b',
246-
},
247-
},
248-
});
240+
emitFastRefreshCompleteEvents();
249241
}
250242
}
251243
});
@@ -393,4 +385,25 @@ function showCompileError() {
393385
throw error;
394386
}
395387

388+
function emitFastRefreshCompleteEvents() {
389+
// Add marker entry in performance timeline
390+
performance.mark('Fast Refresh - Update done', {
391+
detail: {
392+
devtools: {
393+
dataType: 'marker',
394+
color: 'primary',
395+
tooltipText: 'Fast Refresh \u269b',
396+
},
397+
},
398+
});
399+
400+
// Notify CDP clients via internal binding
401+
if (
402+
// $FlowFixMe[prop-missing] - Injected by RuntimeTarget
403+
typeof globalThis.__notifyFastRefreshComplete === 'function'
404+
) {
405+
globalThis.__notifyFastRefreshComplete();
406+
}
407+
}
408+
396409
export default HMRClient;

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
#include "RuntimeAgent.h"
99
#include "SessionState.h"
1010

11+
#include <folly/dynamic.h>
12+
#include <jsinspector-modern/cdp/CdpJson.h>
13+
14+
#include <chrono>
1115
#include <utility>
1216

1317
namespace facebook::react::jsinspector_modern {
@@ -119,6 +123,21 @@ void RuntimeAgent::notifyBindingCalled(
119123
"name", bindingName)("payload", payload)));
120124
}
121125

126+
void RuntimeAgent::notifyFastRefreshComplete() {
127+
if (!sessionState_.isReactNativeApplicationDomainEnabled) {
128+
return;
129+
}
130+
folly::dynamic params = folly::dynamic::object(
131+
"timestamp",
132+
std::chrono::duration_cast<std::chrono::milliseconds>(
133+
std::chrono::system_clock::now().time_since_epoch())
134+
.count());
135+
frontendChannel_(
136+
cdp::jsonNotification(
137+
"ReactNativeApplication.unstable_fastRefreshComplete",
138+
std::move(params)));
139+
}
140+
122141
RuntimeAgent::ExportedState RuntimeAgent::getExportedState() {
123142
return {
124143
.delegateState = delegate_ ? delegate_->getExportedState() : nullptr,

packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgent.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ class RuntimeAgent final {
7272

7373
void notifyBindingCalled(const std::string &bindingName, const std::string &payload);
7474

75+
/**
76+
* Called by RuntimeTarget when JS calls __notifyFastRefreshComplete().
77+
* Emits a ReactNativeApplication.unstable_fastRefreshComplete CDP
78+
* notification if the ReactNativeApplication domain is enabled.
79+
*/
80+
void notifyFastRefreshComplete();
81+
7582
struct ExportedState {
7683
std::unique_ptr<RuntimeAgentDelegate::ExportedState> delegateState;
7784
};

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ void RuntimeTarget::installGlobals() {
4747
// NOTE: RuntimeTarget::installNetworkReporterAPI is in
4848
// RuntimeTargetNetwork.cpp
4949
installNetworkReporterAPI();
50+
51+
installFastRefreshHandler();
5052
}
5153

5254
std::shared_ptr<RuntimeAgent> RuntimeTarget::createAgent(
@@ -128,6 +130,37 @@ void RuntimeTarget::installBindingHandler(const std::string& bindingName) {
128130
});
129131
}
130132

133+
void RuntimeTarget::installFastRefreshHandler() {
134+
jsExecutor_([selfExecutor = executorFromThis()](jsi::Runtime& runtime) {
135+
auto globalObj = runtime.global();
136+
try {
137+
auto name =
138+
jsi::PropNameID::forUtf8(runtime, "__notifyFastRefreshComplete");
139+
globalObj.setProperty(
140+
runtime,
141+
name,
142+
jsi::Function::createFromHostFunction(
143+
runtime,
144+
name,
145+
0,
146+
[selfExecutor](
147+
jsi::Runtime& /*rt*/,
148+
const jsi::Value&,
149+
const jsi::Value*,
150+
size_t) -> jsi::Value {
151+
selfExecutor([](auto& self) {
152+
self.agents_.forEach(
153+
[](auto& agent) { agent.notifyFastRefreshComplete(); });
154+
});
155+
156+
return jsi::Value::undefined();
157+
}));
158+
} catch (jsi::JSError&) {
159+
// Swallow JavaScript exceptions that occur while setting up the global.
160+
}
161+
});
162+
}
163+
131164
void RuntimeTarget::emitDebuggerSessionCreated() {
132165
jsExecutor_([selfExecutor = executorFromThis()](jsi::Runtime& runtime) {
133166
try {

packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,12 @@ class JSINSPECTOR_EXPORT RuntimeTarget : public EnableExecutorFromThis<RuntimeTa
295295
*/
296296
void installGlobals();
297297

298+
/**
299+
* Installs __notifyFastRefreshComplete on the runtime's global object.
300+
* When called from JS, dispatches to all connected RuntimeAgents.
301+
*/
302+
void installFastRefreshHandler();
303+
298304
/**
299305
* Install the console API handler.
300306
*/

0 commit comments

Comments
 (0)