diff --git a/packages/react-native/ReactCommon/jsinspector-modern/HostTarget.cpp b/packages/react-native/ReactCommon/jsinspector-modern/HostTarget.cpp index 12af8080e91a..995238fde041 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/HostTarget.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/HostTarget.cpp @@ -239,7 +239,10 @@ HostTargetDelegate::~HostTargetDelegate() = default; InstanceTarget& HostTarget::registerInstance(InstanceTargetDelegate& delegate) { assert(!currentInstance_ && "Only one instance allowed"); currentInstance_ = InstanceTarget::create( - executionContextManager_, delegate, makeVoidExecutor(executorFromThis())); + executionContextManager_, + delegate, + makeVoidExecutor(executorFromThis()), + delegate_); // Pass HostTargetDelegate reference through sessions_.forEach( [currentInstance = &*currentInstance_](HostTargetSession& session) { session.setCurrentInstance(currentInstance); diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.cpp b/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.cpp index 016e399a8b0f..12020a90a8cc 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.cpp @@ -17,18 +17,21 @@ namespace facebook::react::jsinspector_modern { std::shared_ptr InstanceTarget::create( std::shared_ptr executionContextManager, InstanceTargetDelegate& delegate, - VoidExecutor executor) { - std::shared_ptr instanceTarget{ - new InstanceTarget(executionContextManager, delegate)}; + VoidExecutor executor, + HostTargetDelegate& hostTargetDelegate) { + std::shared_ptr instanceTarget{new InstanceTarget( + executionContextManager, delegate, hostTargetDelegate)}; instanceTarget->setExecutor(std::move(executor)); return instanceTarget; } InstanceTarget::InstanceTarget( std::shared_ptr executionContextManager, - InstanceTargetDelegate& delegate) + InstanceTargetDelegate& delegate, + HostTargetDelegate& hostTargetDelegate) : delegate_(delegate), - executionContextManager_(std::move(executionContextManager)) { + executionContextManager_(std::move(executionContextManager)), + hostTargetDelegate_(hostTargetDelegate) { (void)delegate_; } @@ -77,7 +80,8 @@ RuntimeTarget& InstanceTarget::registerRuntime( .uniqueId = std::nullopt}, delegate, std::move(jsExecutor), - makeVoidExecutor(executorFromThis())); + makeVoidExecutor(executorFromThis()), + hostTargetDelegate_); agents_.forEach([currentRuntime = &*currentRuntime_](InstanceAgent& agent) { agent.setCurrentRuntime(currentRuntime); diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.h b/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.h index 4941bab53acc..ee0aaac31ff5 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.h @@ -24,6 +24,7 @@ namespace facebook::react::jsinspector_modern { class InstanceAgent; class InstanceTracingAgent; class HostTargetTraceRecording; +class HostTargetDelegate; /** * Receives events from an InstanceTarget. This is a shared interface that @@ -55,11 +56,14 @@ class InstanceTarget : public EnableExecutorFromThis { * \param executor An executor that may be used to call methods on this * InstanceTarget while it exists. \c create additionally guarantees that the * executor will not be called after the InstanceTarget is destroyed. + * \param hostTargetDelegate Reference to HostTargetDelegate for + * passing to RuntimeTarget. */ static std::shared_ptr create( std::shared_ptr executionContextManager, InstanceTargetDelegate& delegate, - VoidExecutor executor); + VoidExecutor executor, + HostTargetDelegate& hostTargetDelegate); InstanceTarget(const InstanceTarget&) = delete; InstanceTarget(InstanceTarget&&) = delete; @@ -109,10 +113,12 @@ class InstanceTarget : public EnableExecutorFromThis { * \param delegate The object that will receive events from this target. * The caller is responsible for ensuring that the delegate outlives this * object. + * \param hostTargetDelegate Reference to HostTargetDelegate. */ InstanceTarget( std::shared_ptr executionContextManager, - InstanceTargetDelegate& delegate); + InstanceTargetDelegate& delegate, + HostTargetDelegate& hostTargetDelegate); InstanceTargetDelegate& delegate_; std::shared_ptr currentRuntime_{nullptr}; @@ -125,6 +131,11 @@ class InstanceTarget : public EnableExecutorFromThis { * session - HostTargetTraceRecording. */ std::weak_ptr tracingAgent_; + + /** + * Reference to HostTargetDelegate for passing to RuntimeTarget. + */ + HostTargetDelegate& hostTargetDelegate_; }; } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp index 50562676704a..b65702a829c6 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp @@ -35,9 +35,13 @@ std::shared_ptr RuntimeTarget::create( const ExecutionContextDescription& executionContextDescription, RuntimeTargetDelegate& delegate, RuntimeExecutor jsExecutor, - VoidExecutor selfExecutor) { + VoidExecutor selfExecutor, + HostTargetDelegate& hostTargetDelegate) { std::shared_ptr runtimeTarget{new RuntimeTarget( - executionContextDescription, delegate, std::move(jsExecutor))}; + executionContextDescription, + delegate, + std::move(jsExecutor), + hostTargetDelegate)}; runtimeTarget->setExecutor(std::move(selfExecutor)); runtimeTarget->installGlobals(); return runtimeTarget; @@ -46,14 +50,31 @@ std::shared_ptr RuntimeTarget::create( RuntimeTarget::RuntimeTarget( ExecutionContextDescription executionContextDescription, RuntimeTargetDelegate& delegate, - RuntimeExecutor jsExecutor) + RuntimeExecutor jsExecutor, + HostTargetDelegate& hostTargetDelegate) : executionContextDescription_(std::move(executionContextDescription)), delegate_(delegate), - jsExecutor_(std::move(jsExecutor)) {} + jsExecutor_(std::move(jsExecutor)), + hostTargetDelegate_(hostTargetDelegate) {} + +void RuntimeTarget::consoleTimestampCallback( + std::string_view label, + std::optional start, + std::optional end, + std::optional trackName, + std::optional trackGroup) {} void RuntimeTarget::installGlobals() { // NOTE: RuntimeTarget::installConsoleHandler is in RuntimeTargetConsole.cpp - installConsoleHandler(); + installConsoleHandler([this]( + std::string_view label, + std::optional start, + std::optional end, + std::optional trackName, + std::optional trackGroup) { + consoleTimestampCallback( + label, std::move(start), std::move(end), trackName, trackGroup); + }); installDebuggerSessionObserver(); } @@ -187,6 +208,10 @@ RuntimeTargetController::collectSamplingProfile() { return target_.collectSamplingProfile(); } +HostTargetDelegate& RuntimeTargetController::getHostTargetDelegate() const { + return target_.hostTargetDelegate_; +} + void RuntimeTarget::enableSamplingProfiler() { delegate_.enableSamplingProfiler(); } diff --git a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h index 1dd9b8ef3984..c98ac22e62b4 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h @@ -16,6 +16,7 @@ #include "WeakList.h" #include +#include #include #include @@ -39,8 +40,16 @@ class RuntimeAgent; class RuntimeTracingAgent; class RuntimeAgentDelegate; class RuntimeTarget; +class HostTargetDelegate; struct SessionState; +using ConsoleTimeStampCallback = std::function start, + std::optional end, + std::optional trackName, + std::optional trackGroup)>; + /** * Receives events from a RuntimeTarget. This is a shared interface that * each React Native platform needs to implement in order to integrate with @@ -151,6 +160,11 @@ class RuntimeTargetController { */ tracing::RuntimeSamplingProfile collectSamplingProfile(); + /** + * Get access to HostTargetDelegate. + */ + HostTargetDelegate& getHostTargetDelegate() const; + private: RuntimeTarget& target_; }; @@ -178,12 +192,14 @@ class JSINSPECTOR_EXPORT RuntimeTarget * \param selfExecutor An executor that may be used to call methods on this * RuntimeTarget while it exists. \c create additionally guarantees that the * executor will not be called after the RuntimeTarget is destroyed. + * \param hostTargetDelegate Reference to HostTargetDelegate. */ static std::shared_ptr create( const ExecutionContextDescription& executionContextDescription, RuntimeTargetDelegate& delegate, RuntimeExecutor jsExecutor, - VoidExecutor selfExecutor); + VoidExecutor selfExecutor, + HostTargetDelegate& hostTargetDelegate); RuntimeTarget(const RuntimeTarget&) = delete; RuntimeTarget(RuntimeTarget&&) = delete; @@ -251,7 +267,8 @@ class JSINSPECTOR_EXPORT RuntimeTarget RuntimeTarget( ExecutionContextDescription executionContextDescription, RuntimeTargetDelegate& delegate, - RuntimeExecutor jsExecutor); + RuntimeExecutor jsExecutor, + HostTargetDelegate& hostTargetDelegate); const ExecutionContextDescription executionContextDescription_; RuntimeTargetDelegate& delegate_; @@ -266,6 +283,11 @@ class JSINSPECTOR_EXPORT RuntimeTarget */ std::weak_ptr tracingAgent_; + /** + * Reference to HostTargetDelegate. + */ + HostTargetDelegate& hostTargetDelegate_; + /** * Adds a function with the given name on the runtime's global object, that * when called will send a Runtime.bindingCalled event through all connected @@ -279,10 +301,22 @@ class JSINSPECTOR_EXPORT RuntimeTarget */ void installGlobals(); + /** + * console.timeStamp() callback for propagating events up to HostTarget. + */ + void consoleTimestampCallback( + std::string_view label, + std::optional start, + std::optional end, + std::optional trackName, + std::optional trackGroup); + /** * Install the console API handler. + * \param timestampCallback Callback function for console.timeStamp() event + * propagation. */ - void installConsoleHandler(); + void installConsoleHandler(const ConsoleTimeStampCallback& timestampCallback); /** * Installs __DEBUGGER_SESSION_OBSERVER__ object on the JavaScript's global diff --git a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTargetConsole.cpp b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTargetConsole.cpp index 6b30b9886314..e4082ec6368e 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTargetConsole.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTargetConsole.cpp @@ -6,7 +6,6 @@ */ #include -#include #include #include @@ -389,7 +388,8 @@ auto forwardToOriginalConsole( void consoleTimeStamp( jsi::Runtime& runtime, const jsi::Value* arguments, - size_t argumentsCount) { + size_t argumentsCount, + const ConsoleTimeStampCallback& timestampCallback) { auto& performanceTracer = tracing::PerformanceTracer::getInstance(); if ((!performanceTracer.isTracing() && !ReactPerfettoLogger::isTracing()) || argumentsCount == 0) { @@ -460,6 +460,10 @@ void consoleTimeStamp( } } + if (timestampCallback) { + timestampCallback(label, start, end, trackName, trackGroup); + } + if (performanceTracer.isTracing()) { performanceTracer.reportTimeStamp( label, start, end, trackName, trackGroup, color); @@ -485,7 +489,8 @@ void consoleTimeStamp( void installConsoleTimeStamp( jsi::Runtime& runtime, std::shared_ptr originalConsole, - jsi::Object& consoleObject) { + jsi::Object& consoleObject, + const ConsoleTimeStampCallback& timestampCallback) { consoleObject.setProperty( runtime, "timeStamp", @@ -496,22 +501,25 @@ void installConsoleTimeStamp( forwardToOriginalConsole( originalConsole, "timeStamp", - [](jsi::Runtime& runtime, - const jsi::Value& /*thisVal*/, - const jsi::Value* args, - size_t count) { - consoleTimeStamp(runtime, args, count); + [timestampCallback]( + jsi::Runtime& runtime, + const jsi::Value& /*thisVal*/, + const jsi::Value* args, + size_t count) { + consoleTimeStamp(runtime, args, count, timestampCallback); return jsi::Value::undefined(); }))); } } // namespace -void RuntimeTarget::installConsoleHandler() { +void RuntimeTarget::installConsoleHandler( + const ConsoleTimeStampCallback& timestampCallback) { auto delegateSupportsConsole = delegate_.supportsConsole(); jsExecutor_([selfWeak = weak_from_this(), selfExecutor = executorFromThis(), - delegateSupportsConsole](jsi::Runtime& runtime) { + delegateSupportsConsole, + timestampCallback](jsi::Runtime& runtime) { jsi::Value consolePrototype = jsi::Value::null(); auto originalConsoleVal = runtime.global().getProperty(runtime, "console"); std::shared_ptr originalConsole; @@ -624,7 +632,8 @@ void RuntimeTarget::installConsoleHandler() { /** * console.timeStamp */ - installConsoleTimeStamp(runtime, originalConsole, console); + installConsoleTimeStamp( + runtime, originalConsole, console, timestampCallback); // Install forwarding console methods. #define FORWARDING_CONSOLE_METHOD(name, type) \