diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/InspectorState.cpp b/packages/react-native/ReactCommon/hermes/inspector-modern/InspectorState.cpp index ff447bc39b842a..c1e9d752756273 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/InspectorState.cpp +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/InspectorState.cpp @@ -364,9 +364,9 @@ void InspectorState::Paused::onEnter(InspectorState *prevState) { std::pair InspectorState::Paused::didPause( std::unique_lock &lock) { switch (getPauseReason()) { - case debugger::PauseReason::AsyncTrigger: - inspector_.pendingPauseState_ = AsyncPauseState::None; - break; +// case debugger::PauseReason::AsyncTrigger: +// inspector_.pendingPauseState_ = AsyncPauseState::None; +// break; case debugger::PauseReason::EvalComplete: { assert(pendingEvalPromise_); if (auto userCallbackException = runUserCallback( diff --git a/packages/react-native/ReactCommon/jsinspector-modern/BUCK b/packages/react-native/ReactCommon/jsinspector-modern/BUCK deleted file mode 100644 index a2576b7b578e72..00000000000000 --- a/packages/react-native/ReactCommon/jsinspector-modern/BUCK +++ /dev/null @@ -1,118 +0,0 @@ -load("@fbsource//tools/build_defs:glob_defs.bzl", "subdir_glob") -load("@fbsource//tools/build_defs:platform_defs.bzl", "ANDROID", "APPLE", "CXX", "FBCODE", "WINDOWS") -load("@fbsource//tools/build_defs/oss:rn_defs.bzl", "react_native_xplat_target") -load("@fbsource//xplat/hermes/defs:hermes.bzl", "hermes_is_debugger_enabled") -load("@fbsource//xplat/js/react-native-github/packages/react-native/ReactCommon/jsinspector-modern:DEFS.bzl", "get_fusebox_enabled_flags") -load("//tools/build_defs/oss:rn_defs.bzl", "get_hermes_shared_library_preprocessor_flags", "rn_xplat_cxx_library", "rn_xplat_cxx_test") - -oncall("react_native") - -EXPORTED_HEADERS = [ - "CdpJson.h", - "ConsoleMessage.h", - "ExecutionContext.h", - "ExecutionContextManager.h", - "FallbackRuntimeTargetDelegate.h", - "HostAgent.h", - "HostCommand.h", - "HostTarget.h", - "InspectorFlags.h", - "InspectorInterfaces.h", - "InspectorPackagerConnection.h", - "InstanceAgent.h", - "InstanceTarget.h", - "ReactCdp.h", - "RuntimeAgent.h", - "RuntimeAgentDelegate.h", - "RuntimeTarget.h", - "ScopedExecutor.h", - "SessionState.h", - "StackTrace.h", - "UniqueMonostate.h", - "WeakList.h", - "WebSocketInterfaces.h", -] - -rn_xplat_cxx_library( - name = "jsinspector", - srcs = glob( - ["*.cpp"], - ), - headers = subdir_glob( - [ - ("", "*.def"), - ("", "*.h"), - ], - prefix = "jsinspector-modern", - ), - header_namespace = "", - exported_headers = subdir_glob( - [ - ("", header) - for header in EXPORTED_HEADERS - ], - prefix = "jsinspector-modern", - ), - compiler_flags_disallow_vendor_extensions = True, - compiler_flags_strict_warnings = True, - # jsinspector contains singletons that hold app-global state (InspectorFlags, InspectorImpl). - # Placing it in a shared library makes the singletons safe to use from arbitrary shared libraries - # (even ones that don't depend on one another). - fbandroid_preferred_linkage = "shared", - labels = [ - "pfh:ReactNative_CommonInfrastructurePlaceholder", - ], - platforms = (ANDROID, APPLE, CXX, FBCODE, WINDOWS), - preprocessor_flags = get_hermes_shared_library_preprocessor_flags() + get_fusebox_enabled_flags() + ([ - "-DHERMES_ENABLE_DEBUGGER", - ] if hermes_is_debugger_enabled() else []), - tests = [ - ":tests", - ], - visibility = [ - "PUBLIC", - ], - windows_compiler_flags = ["/WX-"], # Do not treat all warnings as errors - deps = [ - "//third-party/glog:glog", - "//xplat/folly:dynamic", - "//xplat/folly:json", - react_native_xplat_target("reactperflogger:reactperflogger"), - react_native_xplat_target("react/featureflags:featureflags"), - react_native_xplat_target("runtimeexecutor:runtimeexecutor"), - ], - exported_deps = ["//xplat/jsi:jsi"], -) - -rn_xplat_cxx_test( - name = "tests", - srcs = glob([ - "tests/**/*.cpp", - ]), - headers = glob(["tests/**/*.h"]), - contacts = ["oncall+react_native@xmail.facebook.com"], - cxx_labels = [ - "asan-ubsan", - ], - platforms = (ANDROID, APPLE, WINDOWS, CXX), - deps = [ - ":jsinspector", - "//third-party/googletest:gmock_main", - "//third-party/googletest:gtest_main", - "//xplat/ReactNative/react/jsi:hermesinstance", - "//xplat/folly:dynamic", - "//xplat/folly:executor", - "//xplat/folly:format", - "//xplat/folly:json", - "//xplat/folly:json_pointer", - "//xplat/folly:scope_guard", - "//xplat/folly:shared_mutex", - "//xplat/folly:system_thread_id", - "//xplat/folly:thread_local", - "//xplat/folly/executors:manual_executor", - "//xplat/folly/executors:queued_immediate_executor", - "//xplat/hermes/API:HermesAPI", - react_native_xplat_target("hermes/inspector-modern:chrome"), - react_native_xplat_target("react/runtime:runtime"), - ], -) diff --git a/packages/react-native/ReactCommon/jsinspector-modern/CMakeLists.txt b/packages/react-native/ReactCommon/jsinspector-modern/CMakeLists.txt index 73994bd2ecacfd..cbbc44f6dd0162 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/CMakeLists.txt +++ b/packages/react-native/ReactCommon/jsinspector-modern/CMakeLists.txt @@ -23,5 +23,4 @@ target_link_libraries(jsinspector glog react_featureflags runtimeexecutor - reactperflogger ) diff --git a/packages/react-native/ReactCommon/jsinspector-modern/DEFS.bzl b/packages/react-native/ReactCommon/jsinspector-modern/DEFS.bzl deleted file mode 100644 index 559546cd08f43c..00000000000000 --- a/packages/react-native/ReactCommon/jsinspector-modern/DEFS.bzl +++ /dev/null @@ -1,32 +0,0 @@ -load("@fbsource//tools/build_defs:buckconfig.bzl", "read_bool") -load("@fbsource//tools/build_defs/buck2:is_buck2.bzl", "is_buck2") -load("@fbsource//tools/build_defs/oss:rn_defs.bzl", "react_native_xplat_target") - -FLAG_FORCE_ENABLE = "-DREACT_NATIVE_FORCE_ENABLE_FUSEBOX" -FLAG_FORCE_DISABLE = "-DREACT_NATIVE_FORCE_DISABLE_FUSEBOX" -FLAG_ENABLE_DEBUG = "-DREACT_NATIVE_ENABLE_FUSEBOX_DEBUG" - -# Get the Fusebox preprocessor flags to apply based on the active build -# settings. We support per-app feature toggling as well as per-user opt-in/out -# overridding this. -def get_fusebox_enabled_flags(): - force_enable_fusebox = read_bool("react_native", "force_enable_fusebox", False) - force_disable_fusebox = read_bool("react_native", "force_disable_fusebox", False) - - if force_enable_fusebox and force_disable_fusebox: - fail( - "Cannot force enable and disable Fusebox at the same time. " + - "Please supply only one of @//xplat/mode/react-fusebox or " + - "@//xplat/mode/no-react-fusebox.", - ) - - if force_enable_fusebox: - return [FLAG_FORCE_ENABLE] - if force_disable_fusebox: - return [FLAG_FORCE_DISABLE] - - # Temporarily wrapped with is_buck2 to mitigate S429627 - return select({ - react_native_xplat_target("jsinspector-modern/settings:enable_fusebox_debug"): [FLAG_ENABLE_DEBUG], - "DEFAULT": [], - }) if is_buck2() else [] diff --git a/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.cpp b/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.cpp index 260c5aadd6f584..46c1a94df312e1 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.cpp @@ -15,8 +15,6 @@ #include -#include - using namespace std::chrono; using namespace std::literals::string_view_literals; @@ -148,41 +146,25 @@ void HostAgent::handleRequest(const cdp::PreparsedRequest& req) { shouldSendOKResponse = true; isFinishedHandlingRequest = true; } else if (req.method == "Tracing.start") { - // @cdp Tracing.start support is experimental. - if (FuseboxTracer::getFuseboxTracer().startTracing()) { - shouldSendOKResponse = true; - } else { - frontendChannel_(cdp::jsonError( - req.id, - cdp::ErrorCode::InternalError, - "Tracing session already started")); - return; - } + // @cdp Tracing.start is implemented as a stub only. + frontendChannel_(cdp::jsonNotification( + // @cdp Tracing.bufferUsage is implemented as a stub only. + "Tracing.bufferUsage", + folly::dynamic::object("percentFull", 0)("eventCount", 0)("value", 0))); + shouldSendOKResponse = true; isFinishedHandlingRequest = true; } else if (req.method == "Tracing.end") { - // @cdp Tracing.end support is experimental. - bool firstChunk = true; - auto id = req.id; - bool wasStopped = FuseboxTracer::getFuseboxTracer().stopTracing( - [this, firstChunk, id](const folly::dynamic& eventsChunk) { - if (firstChunk) { - frontendChannel_(cdp::jsonResult(id)); - } - frontendChannel_(cdp::jsonNotification( - "Tracing.dataCollected", - folly::dynamic::object("value", eventsChunk))); - }); - if (!wasStopped) { - frontendChannel_(cdp::jsonError( - req.id, - cdp::ErrorCode::InternalError, - "Tracing session not started")); - return; - } + // @cdp Tracing.end is implemented as a stub only. frontendChannel_(cdp::jsonNotification( + // @cdp Tracing.dataCollected is implemented as a stub only. + "Tracing.dataCollected", + folly::dynamic::object("value", folly::dynamic::array()))); + frontendChannel_(cdp::jsonNotification( + // @cdp Tracing.tracingComplete is implemented as a stub only. "Tracing.tracingComplete", folly::dynamic::object("dataLossOccurred", false))); - return; + shouldSendOKResponse = true; + isFinishedHandlingRequest = true; } if (!isFinishedHandlingRequest && instanceAgent_ && diff --git a/packages/react-native/ReactCommon/jsinspector-modern/HostTarget.h.rej b/packages/react-native/ReactCommon/jsinspector-modern/HostTarget.h.rej deleted file mode 100644 index 5e8bc41a6953f6..00000000000000 --- a/packages/react-native/ReactCommon/jsinspector-modern/HostTarget.h.rej +++ /dev/null @@ -1,265 +0,0 @@ ---- HostTarget.h -+++ HostTarget.h -@@ -1,256 +1,261 @@ - /* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - - #pragma once - - #include "ExecutionContextManager.h" - #include "HostCommand.h" - #include "InspectorInterfaces.h" - #include "InstanceTarget.h" - #include "ScopedExecutor.h" - #include "WeakList.h" - - #include - #include - - #ifndef JSINSPECTOR_EXPORT - #ifdef _MSC_VER - #ifdef CREATE_SHARED_LIBRARY - #define JSINSPECTOR_EXPORT __declspec(dllexport) - #else - #define JSINSPECTOR_EXPORT - #endif // CREATE_SHARED_LIBRARY - #else // _MSC_VER - #define JSINSPECTOR_EXPORT __attribute__((visibility("default"))) - #endif // _MSC_VER - #endif // !defined(JSINSPECTOR_EXPORT) - - namespace facebook::react::jsinspector_modern { - - class HostTargetSession; - class HostAgent; - class HostCommandSender; - class HostTarget; - - struct HostTargetMetadata { -+ std::optional appIdentifier; -+ std::optional deviceName; - std::optional integrationName; -+ std::optional platform; -+ std::optional reactNativeVersion; - }; - - /** - * Receives events from a HostTarget. This is a shared interface that each - * React Native platform needs to implement in order to integrate with the - * debugging stack. - */ - class HostTargetDelegate { - public: - HostTargetDelegate() = default; - HostTargetDelegate(const HostTargetDelegate&) = delete; - HostTargetDelegate(HostTargetDelegate&&) = default; - HostTargetDelegate& operator=(const HostTargetDelegate&) = delete; - HostTargetDelegate& operator=(HostTargetDelegate&&) = default; - - // TODO(moti): This is 1:1 the shape of the corresponding CDP message - - // consider reusing typed/generated CDP interfaces when we have those. - struct PageReloadRequest { - // It isn't clear what the ignoreCache parameter of @cdp Page.reload should - // mean in React Native. We parse it, but don't do anything with it yet. - std::optional ignoreCache; - - // TODO: Implement scriptToEvaluateOnLoad parameter of @cdp Page.reload. - std::optional scriptToEvaluateOnLoad; - - /** - * Equality operator, useful for unit tests - */ - inline bool operator==(const PageReloadRequest& rhs) const { - return ignoreCache == rhs.ignoreCache && - scriptToEvaluateOnLoad == rhs.scriptToEvaluateOnLoad; - } - }; - - struct OverlaySetPausedInDebuggerMessageRequest { - /** - * The message to display in the overlay. If nullopt, hide the overlay. - */ - std::optional message; - - /** - * Equality operator, useful for unit tests - */ - inline bool operator==( - const OverlaySetPausedInDebuggerMessageRequest& rhs) const { - return message == rhs.message; - } - }; - - virtual ~HostTargetDelegate(); - - /** -- * Returns a metadata object describing the host. -+ * Returns a metadata object describing the host. This is called on an -+ * initial response to @cdp ReactNativeApplication.enable. - */ - virtual HostTargetMetadata getMetadata() = 0; - - /** - * Called when the debugger requests a reload of the page. This is called on - * the thread on which messages are dispatched to the session (that is, where - * ILocalConnection::sendMessage was called). - */ - virtual void onReload(const PageReloadRequest& request) = 0; - - /** - * Called when the debugger requests that the "paused in debugger" overlay be - * shown or hidden. If the message is nullopt, hide the overlay, otherwise - * show it with the given message. This is called on the inspector thread. - * - * If this method is called with a non-null message, it's guaranteed to - * eventually be called again with a null message. In all other respects, - * the timing and payload of these messages are fully controlled by the - * client. - */ - virtual void onSetPausedInDebuggerMessage( - const OverlaySetPausedInDebuggerMessageRequest& request) = 0; - }; - - /** - * The limited interface that HostTarget exposes to its associated - * sessions/agents. - */ - class HostTargetController final { - public: - explicit HostTargetController(HostTarget& target); - - HostTargetDelegate& getDelegate(); - - bool hasInstance() const; - - /** - * Increments the target's pause overlay counter. The counter represents the - * exact number of Agents that have (concurrently) requested the pause - * overlay to be shown. It's the caller's responsibility to only call this - * when the pause overlay's requested state transitions from hidden to - * visible. - */ - void incrementPauseOverlayCounter(); - - /** - * Decrements the target's pause overlay counter. The counter represents the - * exact number of Agents that have (concurrently) requested the pause - * overlay to be shown. It's the caller's responsibility to only call this - * when the pause overlay's requested state transitions from hidden to - * visible. - * \returns false if the counter has reached 0, otherwise true. - */ - bool decrementPauseOverlayCounter(); - - private: - HostTarget& target_; - size_t pauseOverlayCounter_{0}; - }; - - /** - * The top-level Target in a React Native app. This is equivalent to the - * "Host" in React Native's architecture - the entity that manages the - * lifecycle of a React Instance. - */ - class JSINSPECTOR_EXPORT HostTarget - : public EnableExecutorFromThis { - public: - /** - * Constructs a new HostTarget. - * \param delegate The HostTargetDelegate that will - * receive events from this HostTarget. The caller is responsible for ensuring - * that the HostTargetDelegate outlives this object. - * \param executor An executor that may be used to call methods on this - * HostTarget while it exists. \c create additionally guarantees that the - * executor will not be called after the HostTarget is destroyed. - * \note Copies of the provided executor may be destroyed on arbitrary - * threads, including after the HostTarget is destroyed. Callers must ensure - * that such destructor calls are safe - e.g. if using a lambda as the - * executor, all captured values must be safe to destroy from any thread. - */ - static std::shared_ptr create( - HostTargetDelegate& delegate, - VoidExecutor executor); - - HostTarget(const HostTarget&) = delete; - HostTarget(HostTarget&&) = delete; - HostTarget& operator=(const HostTarget&) = delete; - HostTarget& operator=(HostTarget&&) = delete; - ~HostTarget(); - - /** - * Creates a new Session connected to this HostTarget, wrapped in an - * interface which is compatible with \c IInspector::addPage. - * The caller is responsible for destroying the connection before HostTarget - * is destroyed, on the same thread where HostTarget's constructor and - * destructor execute. - */ - std::unique_ptr connect( - std::unique_ptr connectionToFrontend); - - /** - * Registers an instance with this HostTarget. - * \param delegate The InstanceTargetDelegate that will receive events from - * this InstanceTarget. The caller is responsible for ensuring that the - * InstanceTargetDelegate outlives this object. - * \return An InstanceTarget reference representing the newly created - * instance. This reference is only valid until unregisterInstance is called - * (or the HostTarget is destroyed). \pre There isn't currently an instance - * registered with this HostTarget. - */ - InstanceTarget& registerInstance(InstanceTargetDelegate& delegate); - - /** - * Unregisters an instance from this HostTarget. - * \param instance The InstanceTarget reference previously returned by - * registerInstance. - */ - void unregisterInstance(InstanceTarget& instance); - - /** - * Sends an imperative command to the HostTarget. May be called from any - * thread. - */ - void sendCommand(HostCommand command); - - private: - /** - * Constructs a new HostTarget. - * The caller must call setExecutor immediately afterwards. - * \param delegate The HostTargetDelegate that will - * receive events from this HostTarget. The caller is responsible for ensuring - * that the HostTargetDelegate outlives this object. - */ - HostTarget(HostTargetDelegate& delegate); - - HostTargetDelegate& delegate_; - WeakList sessions_; - HostTargetController controller_{*this}; - // executionContextManager_ is a shared_ptr to guarantee its validity while - // the InstanceTarget is alive (just in case the InstanceTarget ends up - // briefly outliving the HostTarget, which it generally shouldn't). - std::shared_ptr executionContextManager_; - std::shared_ptr currentInstance_{nullptr}; - std::unique_ptr commandSender_; - - inline HostTargetDelegate& getDelegate() { - return delegate_; - } - - inline bool hasInstance() const { - return currentInstance_ != nullptr; - } - - // Necessary to allow HostAgent to access HostTarget's internals in a - // controlled way (i.e. only HostTargetController gets friend access, while - // HostAgent itself doesn't). - friend class HostTargetController; - }; - - const folly::dynamic hostMetadataToDynamic(const HostTargetMetadata& metadata); - - } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp b/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp index 9d28790db29842..bba796a4f5b348 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp @@ -8,6 +8,7 @@ #include "InspectorFlags.h" #include +//#include namespace facebook::react::jsinspector_modern { @@ -33,7 +34,19 @@ void InspectorFlags::dangerouslyResetFlags() { const InspectorFlags::Values& InspectorFlags::loadFlagsAndAssertUnchanged() const { InspectorFlags::Values newValues = { - .fuseboxEnabled = true + .fuseboxEnabled = +#if defined(REACT_NATIVE_FORCE_ENABLE_FUSEBOX) + true, +#elif defined(REACT_NATIVE_FORCE_DISABLE_FUSEBOX) + false, +#elif defined(HERMES_ENABLE_DEBUGGER) && \ + defined(REACT_NATIVE_ENABLE_FUSEBOX_DEBUG) + true, +#elif defined(HERMES_ENABLE_DEBUGGER) + ReactNativeFeatureFlags::fuseboxEnabledDebug(), +#else + ReactNativeFeatureFlags::fuseboxEnabledRelease(), +#endif }; if (cachedValues_.has_value() && !inconsistentFlagsStateLogged_) { diff --git a/packages/react-native/ReactCommon/jsinspector-modern/React-jsinspector.podspec b/packages/react-native/ReactCommon/jsinspector-modern/React-jsinspector.podspec index 6840b83e49d63b..86783dcfd9b633 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/React-jsinspector.podspec +++ b/packages/react-native/ReactCommon/jsinspector-modern/React-jsinspector.podspec @@ -16,12 +16,9 @@ else source[:tag] = "v#{version}" end -folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DFOLLY_CFG_NO_COROUTINES=1 -DFOLLY_HAVE_CLOCK_GETTIME=1 -Wno-comma -Wno-shorten-64-to-32' -folly_version = '2023.08.07.00' - -# folly_config = get_folly_config() -# folly_compiler_flags = folly_config[:compiler_flags] -# folly_version = folly_config[:version] +folly_config = get_folly_config() +folly_compiler_flags = folly_config[:compiler_flags] +folly_version = folly_config[:version] use_frameworks = ENV['USE_FRAMEWORKS'] != nil @@ -53,11 +50,10 @@ Pod::Spec.new do |s| s.dependency "glog" s.dependency "RCT-Folly", folly_version - # s.dependency "React-featureflags" + s.dependency "React-featureflags" s.dependency "DoubleConversion" s.dependency "React-runtimeexecutor", version s.dependency "React-jsi" - s.dependency "React-perflogger", version if ENV["USE_HERMES"] == nil || ENV["USE_HERMES"] == "1" s.dependency "hermes-engine" end diff --git a/packages/react-native/ReactCommon/jsinspector-modern/settings/BUCK b/packages/react-native/ReactCommon/jsinspector-modern/settings/BUCK deleted file mode 100644 index a69719289e0b51..00000000000000 --- a/packages/react-native/ReactCommon/jsinspector-modern/settings/BUCK +++ /dev/null @@ -1,14 +0,0 @@ -oncall("react_native") - -# Internal React Native DevTools (Fusebox) rollout (H1 2024). Apps can apply -# the constraint value "enable_fusebox_debug" to opt in. -constraint_setting( - name = "fusebox_internal_rollout", - visibility = ["PUBLIC"], -) - -constraint_value( - name = "enable_fusebox_debug", - constraint_setting = ":fusebox_internal_rollout", - visibility = ["PUBLIC"], -)