Marketplace móvil para negocios locales mexicanos. Estructura inicial: - apps/backend (NestJS API) - apps/frontend (React Web) - apps/mobile (Expo/React Native) - apps/mcp-server (Claude MCP Server) - apps/whatsapp-service (WhatsApp Business API) - database/ (PostgreSQL DDL) - docs/ (Documentación) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
384 lines
13 KiB
C++
384 lines
13 KiB
C++
/*
|
|
* 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 "NetworkIOAgent.h"
|
|
#include "PerfMonitorV2.h"
|
|
#include "ScopedExecutor.h"
|
|
#include "WeakList.h"
|
|
|
|
#include <optional>
|
|
#include <string>
|
|
|
|
#include <jsinspector-modern/tracing/TracingMode.h>
|
|
#include <jsinspector-modern/tracing/TracingState.h>
|
|
|
|
#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 HostTracingAgent;
|
|
class HostCommandSender;
|
|
class HostRuntimeBinding;
|
|
class HostTarget;
|
|
class HostTargetTraceRecording;
|
|
|
|
struct HostTargetMetadata {
|
|
std::optional<std::string> appDisplayName{};
|
|
std::optional<std::string> appIdentifier{};
|
|
std::optional<std::string> deviceName{};
|
|
std::optional<std::string> integrationName;
|
|
std::optional<std::string> platform{};
|
|
std::optional<std::string> 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 LoadNetworkResourceDelegate {
|
|
public:
|
|
HostTargetDelegate() = default;
|
|
HostTargetDelegate(const HostTargetDelegate &) = delete;
|
|
HostTargetDelegate(HostTargetDelegate &&) = delete;
|
|
HostTargetDelegate &operator=(const HostTargetDelegate &) = delete;
|
|
HostTargetDelegate &operator=(HostTargetDelegate &&) = delete;
|
|
|
|
// 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<bool> ignoreCache;
|
|
|
|
// TODO: Implement scriptToEvaluateOnLoad parameter of @cdp Page.reload.
|
|
std::optional<std::string> 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<std::string> message;
|
|
|
|
/**
|
|
* Equality operator, useful for unit tests
|
|
*/
|
|
inline bool operator==(const OverlaySetPausedInDebuggerMessageRequest &rhs) const
|
|
{
|
|
return message == rhs.message;
|
|
}
|
|
};
|
|
|
|
virtual ~HostTargetDelegate() override;
|
|
|
|
/**
|
|
* 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;
|
|
|
|
/**
|
|
* [Experimental] Called when the runtime has new data for the V2 Perf
|
|
* Monitor overlay. This is called on the inspector thread.
|
|
*/
|
|
virtual void unstable_onPerfIssueAdded(const PerfIssuePayload & /*issue*/) {}
|
|
|
|
/**
|
|
* Called by NetworkIOAgent on handling a `Network.loadNetworkResource` CDP
|
|
* request. Platform implementations should override this to perform a
|
|
* network request of the given URL, and use listener's callbacks on receipt
|
|
* of headers, data chunks, and errors.
|
|
*/
|
|
void loadNetworkResource(
|
|
const LoadNetworkResourceRequest & /*params*/,
|
|
ScopedExecutor<NetworkRequestListener> /*executor*/) override
|
|
{
|
|
throw NotImplementedException(
|
|
"LoadNetworkResourceDelegate.loadNetworkResource is not implemented by this host target delegate.");
|
|
}
|
|
|
|
/**
|
|
* [Experimental] Will be called at the CDP session initialization to get the
|
|
* trace recording that may have been stashed by the Host from the previous
|
|
* background session.
|
|
*
|
|
* \return the trace recording state if there is one that needs to be
|
|
* displayed, otherwise std::nullopt.
|
|
*/
|
|
virtual std::optional<tracing::TraceRecordingState> unstable_getTraceRecordingThatWillBeEmittedOnInitialization()
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* The limited interface that HostTarget exposes to its associated
|
|
* sessions/agents.
|
|
*/
|
|
class HostTargetController final {
|
|
public:
|
|
explicit HostTargetController(HostTarget &target);
|
|
|
|
HostTargetDelegate &getDelegate();
|
|
|
|
bool hasInstance() const;
|
|
|
|
/**
|
|
* [Experimental] Install a runtime binding subscribing to new Performance
|
|
* Issues, which we broadcast to the V2 Perf Monitor overlay via
|
|
* \ref HostTargetDelegate::unstable_onPerfIssueAdded.
|
|
*/
|
|
void installPerfIssuesBinding();
|
|
|
|
/**
|
|
* 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();
|
|
|
|
/**
|
|
* Starts trace recording for this HostTarget.
|
|
*
|
|
* \param mode In which mode to start the trace recording.
|
|
* \return false if already tracing, true otherwise.
|
|
*/
|
|
bool startTracing(tracing::Mode mode);
|
|
|
|
/**
|
|
* Stops previously started trace recording.
|
|
*/
|
|
tracing::TraceRecordingState stopTracing();
|
|
|
|
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<HostTarget> {
|
|
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<HostTarget> 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<ILocalConnection> connect(std::unique_ptr<IRemoteConnection> 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 ®isterInstance(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);
|
|
|
|
/**
|
|
* Creates a new HostTracingAgent.
|
|
* This Agent is not owned by the HostTarget. The Agent will be destroyed at
|
|
* the end of the tracing session.
|
|
*
|
|
* \param state A reference to the state of the active trace recording.
|
|
*/
|
|
std::shared_ptr<HostTracingAgent> createTracingAgent(tracing::TraceRecordingState &state);
|
|
|
|
/**
|
|
* Starts trace recording for this HostTarget.
|
|
*
|
|
* \param mode In which mode to start the trace recording.
|
|
* \return false if already tracing, true otherwise.
|
|
*/
|
|
bool startTracing(tracing::Mode mode);
|
|
|
|
/**
|
|
* Stops previously started trace recording.
|
|
*/
|
|
tracing::TraceRecordingState stopTracing();
|
|
|
|
/**
|
|
* Returns the state of the background trace, running, stopped, or disabled
|
|
*/
|
|
tracing::TracingState tracingState() const;
|
|
|
|
/**
|
|
* Returns whether there is an active session with the Fusebox client, i.e.
|
|
* with Chrome DevTools Frontend fork for React Native.
|
|
*/
|
|
bool hasActiveSessionWithFuseboxClient() const;
|
|
|
|
/**
|
|
* Emits the trace recording for the first active session with the Fusebox
|
|
* client.
|
|
*
|
|
* @see \c hasActiveFrontendSession
|
|
*/
|
|
void emitTraceRecordingForFirstFuseboxClient(tracing::TraceRecordingState traceRecording) const;
|
|
|
|
/**
|
|
* Emits a system state changed event to all active sessions.
|
|
*/
|
|
void emitSystemStateChanged(bool isSingleHost) const;
|
|
|
|
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<HostTargetSession> 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> executionContextManager_;
|
|
std::shared_ptr<InstanceTarget> currentInstance_{nullptr};
|
|
std::unique_ptr<HostCommandSender> commandSender_;
|
|
std::unique_ptr<PerfMonitorUpdateHandler> perfMonitorUpdateHandler_;
|
|
std::unique_ptr<HostRuntimeBinding> perfMetricsBinding_;
|
|
|
|
/**
|
|
* Current pending trace recording, which encapsulates the configuration of
|
|
* the tracing session and the state.
|
|
*
|
|
* Should only be allocated when there is an active tracing session.
|
|
*/
|
|
std::unique_ptr<HostTargetTraceRecording> traceRecording_{nullptr};
|
|
|
|
inline HostTargetDelegate &getDelegate()
|
|
{
|
|
return delegate_;
|
|
}
|
|
|
|
inline bool hasInstance() const
|
|
{
|
|
return currentInstance_ != nullptr;
|
|
}
|
|
|
|
/**
|
|
* [Experimental] Install a runtime binding subscribing to new Peformance
|
|
* Issues, which we broadcast to the V2 Perf Monitor overlay via
|
|
* \ref HostTargetDelegate::unstable_onPerfMonitorUpdate.
|
|
*/
|
|
void installPerfIssuesBinding();
|
|
|
|
// 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;
|
|
};
|
|
|
|
folly::dynamic createHostMetadataPayload(const HostTargetMetadata &metadata);
|
|
|
|
} // namespace facebook::react::jsinspector_modern
|