File tree Expand file tree Collapse file tree 5 files changed +87
-9
lines changed
ReactCommon/jsinspector-modern Expand file tree Collapse file tree 5 files changed +87
-9
lines changed Original file line number Diff line number Diff 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+
396409export default HMRClient ;
Original file line number Diff line number Diff line change 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
1317namespace 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+
122141RuntimeAgent::ExportedState RuntimeAgent::getExportedState () {
123142 return {
124143 .delegateState = delegate_ ? delegate_->getExportedState () : nullptr ,
Original file line number Diff line number Diff 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 };
Original file line number Diff line number Diff 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
5254std::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+
131164void RuntimeTarget::emitDebuggerSessionCreated () {
132165 jsExecutor_ ([selfExecutor = executorFromThis ()](jsi::Runtime& runtime) {
133166 try {
Original file line number Diff line number Diff 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 */
You can’t perform that action at this time.
0 commit comments