Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/react-native/React/Base/RCTBridge.mm
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@ void onReload(const PageReloadRequest &request) override
[bridge_ reload];
}

void onSetPausedInDebuggerMessage(const OverlaySetPausedInDebuggerMessageRequest &) override
{
// TODO(moti): Implement this
}

private:
__weak RCTBridge *bridge_;
};
Expand Down
7 changes: 7 additions & 0 deletions packages/react-native/ReactAndroid/api/ReactAndroid.api
Original file line number Diff line number Diff line change
Expand Up @@ -1175,6 +1175,7 @@ public class com/facebook/react/bridge/ReactInstanceManagerInspectorTarget : jav

public abstract interface class com/facebook/react/bridge/ReactInstanceManagerInspectorTarget$TargetDelegate {
public abstract fun onReload ()V
public abstract fun onSetPausedInDebuggerMessage (Ljava/lang/String;)V
}

public class com/facebook/react/bridge/ReactMarker {
Expand Down Expand Up @@ -2126,6 +2127,7 @@ public abstract class com/facebook/react/devsupport/DevSupportManagerBase : com/
public fun handleException (Ljava/lang/Exception;)V
public fun hasUpToDateJSBundleInCache ()Z
protected fun hideDevLoadingView ()V
public fun hidePausedInDebuggerOverlay ()V
public fun hideRedboxDialog ()V
public fun isPackagerRunning (Lcom/facebook/react/devsupport/interfaces/PackagerStatusCallback;)V
public fun onNewReactContextCreated (Lcom/facebook/react/bridge/ReactContext;)V
Expand All @@ -2145,6 +2147,7 @@ public abstract class com/facebook/react/devsupport/DevSupportManagerBase : com/
public fun showDevOptionsDialog ()V
public fun showNewJSError (Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;I)V
public fun showNewJavaError (Ljava/lang/String;Ljava/lang/Throwable;)V
public fun showPausedInDebuggerOverlay (Ljava/lang/String;)V
public fun startInspector ()V
public fun stopInspector ()V
public fun toggleElementInspector ()V
Expand Down Expand Up @@ -2290,6 +2293,7 @@ public class com/facebook/react/devsupport/ReleaseDevSupportManager : com/facebo
public fun handleException (Ljava/lang/Exception;)V
public fun handleReloadJS ()V
public fun hasUpToDateJSBundleInCache ()Z
public fun hidePausedInDebuggerOverlay ()V
public fun hideRedboxDialog ()V
public fun isPackagerRunning (Lcom/facebook/react/devsupport/interfaces/PackagerStatusCallback;)V
public fun loadSplitBundleFromServer (Ljava/lang/String;Lcom/facebook/react/devsupport/interfaces/DevSplitBundleCallback;)V
Expand All @@ -2309,6 +2313,7 @@ public class com/facebook/react/devsupport/ReleaseDevSupportManager : com/facebo
public fun showDevOptionsDialog ()V
public fun showNewJSError (Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;I)V
public fun showNewJavaError (Ljava/lang/String;Ljava/lang/Throwable;)V
public fun showPausedInDebuggerOverlay (Ljava/lang/String;)V
public fun startInspector ()V
public fun stopInspector ()V
public fun toggleElementInspector ()V
Expand Down Expand Up @@ -2400,6 +2405,7 @@ public abstract interface class com/facebook/react/devsupport/interfaces/DevSupp
public abstract fun getSourceUrl ()Ljava/lang/String;
public abstract fun handleReloadJS ()V
public abstract fun hasUpToDateJSBundleInCache ()Z
public abstract fun hidePausedInDebuggerOverlay ()V
public abstract fun hideRedboxDialog ()V
public abstract fun isPackagerRunning (Lcom/facebook/react/devsupport/interfaces/PackagerStatusCallback;)V
public abstract fun loadSplitBundleFromServer (Ljava/lang/String;Lcom/facebook/react/devsupport/interfaces/DevSplitBundleCallback;)V
Expand All @@ -2419,6 +2425,7 @@ public abstract interface class com/facebook/react/devsupport/interfaces/DevSupp
public abstract fun showDevOptionsDialog ()V
public abstract fun showNewJSError (Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;I)V
public abstract fun showNewJavaError (Ljava/lang/String;Ljava/lang/Throwable;)V
public abstract fun showPausedInDebuggerOverlay (Ljava/lang/String;)V
public abstract fun startInspector ()V
public abstract fun stopInspector ()V
public abstract fun toggleElementInspector ()V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1494,6 +1494,15 @@ private void processPackage(
public void onReload() {
UiThreadUtil.runOnUiThread(() -> mDevSupportManager.handleReloadJS());
}

@Override
public void onSetPausedInDebuggerMessage(@Nullable String message) {
if (message == null) {
mDevSupportManager.hidePausedInDebuggerOverlay();
} else {
mDevSupportManager.showPausedInDebuggerOverlay(message);
}
}
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@
import com.facebook.jni.HybridData;
import com.facebook.proguard.annotations.DoNotStripAny;
import java.util.concurrent.Executor;
import javax.annotation.Nullable;

@DoNotStripAny
public class ReactInstanceManagerInspectorTarget implements AutoCloseable {
public interface TargetDelegate {
public void onReload();

public void onSetPausedInDebuggerMessage(@Nullable String message);
}

private final HybridData mHybridData;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1164,4 +1164,34 @@ public void openDebugger() {
mDevServerHelper.openDebugger(
mCurrentContext, mApplicationContext.getString(R.string.catalyst_open_debugger_error));
}

private @Nullable AlertDialog mPausedInDebuggerDialog;

@Override
public void showPausedInDebuggerOverlay(String message) {
UiThreadUtil.runOnUiThread(
() -> {
if (mPausedInDebuggerDialog != null) {
mPausedInDebuggerDialog.dismiss();
}
Activity context = mReactInstanceDevHelper.getCurrentActivity();
if (context == null || context.isFinishing()) {
return;
}
mPausedInDebuggerDialog =
new AlertDialog.Builder(context).setMessage(message).setCancelable(false).create();
mPausedInDebuggerDialog.show();
});
}

@Override
public void hidePausedInDebuggerOverlay() {
UiThreadUtil.runOnUiThread(
() -> {
if (mPausedInDebuggerDialog != null) {
mPausedInDebuggerDialog.dismiss();
mPausedInDebuggerDialog = null;
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -207,4 +207,10 @@ public void handleException(Exception e) {

@Override
public void openDebugger() {}

@Override
public void showPausedInDebuggerOverlay(String message) {}

@Override
public void hidePausedInDebuggerOverlay() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ public interface DevSupportManager : JSExceptionHandler {
/** Attempt to open the JS debugger on the host machine. */
public fun openDebugger()

/** Shows the "paused in debugger" overlay with the given message. */
public fun showPausedInDebuggerOverlay(message: String)

/** Hides the "paused in debugger" overlay, if currently shown. */
public fun hidePausedInDebuggerOverlay()

/**
* The PackagerLocationCustomizer allows you to have a dynamic packager location that is
* determined right before loading the packager. Your customizer must call |callback|, as loading
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.facebook.infer.annotation.Nullsafe;
import com.facebook.infer.annotation.ThreadConfined;
import com.facebook.infer.annotation.ThreadSafe;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.JSEngineResolutionAlgorithm;
import com.facebook.react.MemoryPressureRouter;
import com.facebook.react.ReactHost;
Expand Down Expand Up @@ -466,6 +467,15 @@ public TaskInterface<Void> reload(String reason) {
.continueWithTask(Task::getResult);
}

@DoNotStrip
private void setPausedInDebuggerMessage(@Nullable String message) {
if (message == null) {
mDevSupportManager.hidePausedInDebuggerOverlay();
} else {
mDevSupportManager.showPausedInDebuggerOverlay(message);
}
}

/**
* Entrypoint to destroy the ReactInstance. If the ReactInstance is reloading, will wait until
* reload is finished, before destroying.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ void ReactInstanceManagerInspectorTarget::TargetDelegate::onReload() const {
method(self());
}

void ReactInstanceManagerInspectorTarget::TargetDelegate::
onSetPausedInDebuggerMessage(
const OverlaySetPausedInDebuggerMessageRequest& request) const {
auto method = javaClassStatic()->getMethod<void(local_ref<JString>)>(
"onSetPausedInDebuggerMessage");
method(self(), request.message ? make_jstring(*request.message) : nullptr);
}

ReactInstanceManagerInspectorTarget::ReactInstanceManagerInspectorTarget(
jni::alias_ref<ReactInstanceManagerInspectorTarget::jhybridobject> jobj,
jni::alias_ref<JExecutor::javaobject> executor,
Expand Down Expand Up @@ -82,6 +90,11 @@ void ReactInstanceManagerInspectorTarget::onReload(
delegate_->onReload();
}

void ReactInstanceManagerInspectorTarget::onSetPausedInDebuggerMessage(
const OverlaySetPausedInDebuggerMessageRequest& request) {
delegate_->onSetPausedInDebuggerMessage(request);
}

HostTarget* ReactInstanceManagerInspectorTarget::getInspectorTarget() {
return inspectorTarget_.get();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class ReactInstanceManagerInspectorTarget
"Lcom/facebook/react/bridge/ReactInstanceManagerInspectorTarget$TargetDelegate;";

void onReload() const;
void onSetPausedInDebuggerMessage(
const OverlaySetPausedInDebuggerMessageRequest& request) const;
};

public:
Expand All @@ -44,9 +46,13 @@ class ReactInstanceManagerInspectorTarget

static void registerNatives();

void onReload(const PageReloadRequest& request) override;
jsinspector_modern::HostTarget* getInspectorTarget();

// HostTargetDelegate methods
void onReload(const PageReloadRequest& request) override;
void onSetPausedInDebuggerMessage(
const OverlaySetPausedInDebuggerMessageRequest&) override;

private:
friend HybridBase;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ void JReactHostInspectorTarget::onReload(const PageReloadRequest& request) {
javaReactHostImpl_->reload("CDP Page.reload");
}

void JReactHostInspectorTarget::onSetPausedInDebuggerMessage(
const OverlaySetPausedInDebuggerMessageRequest& request) {
javaReactHostImpl_->setPausedInDebuggerMessage(request.message);
}

HostTarget* JReactHostInspectorTarget::getInspectorTarget() {
return inspectorTarget_ ? inspectorTarget_.get() : nullptr;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ struct JReactHostImpl : public jni::JavaClass<JReactHostImpl> {
"reload");
return method(self(), reason);
}

void setPausedInDebuggerMessage(std::optional<std::string> message) {
static auto method =
javaClassStatic()->getMethod<void(jni::local_ref<jni::JString>)>(
"setPausedInDebuggerMessage");
method(self(), message ? jni::make_jstring(*message) : nullptr);
}
};

class JReactHostInspectorTarget
Expand All @@ -48,6 +55,8 @@ class JReactHostInspectorTarget
static void registerNatives();

void onReload(const PageReloadRequest& request) override;
void onSetPausedInDebuggerMessage(
const OverlaySetPausedInDebuggerMessageRequest&) override;

jsinspector_modern::HostTarget* getInspectorTarget();

Expand Down
11 changes: 11 additions & 0 deletions packages/react-native/ReactCommon/jsinspector-modern/CdpJson.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,15 @@ std::string jsonNotification(
return folly::toJson(std::move(dynamicNotification));
}

std::string jsonRequest(
RequestId id,
std::string_view method,
std::optional<folly::dynamic> params) {
auto dynamicRequest = folly::dynamic::object("id", id)("method", method);
if (params) {
dynamicRequest("params", *params);
}
return folly::toJson(std::move(dynamicRequest));
}

} // namespace facebook::react::jsinspector_modern::cdp
18 changes: 16 additions & 2 deletions packages/react-native/ReactCommon/jsinspector-modern/CdpJson.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,29 @@ std::string jsonResult(
const folly::dynamic& result = folly::dynamic::object());

/**
* Returns a JSON-formatted string representing a unilateral notifcation.
* Returns a JSON-formatted string representing a unilateral notification.
*
* {"method": <method>, "params": <params>}
*
* \param method Notification (aka "event") method.
* \param params Optional payload pbject.
* \param params Optional payload object.
*/
std::string jsonNotification(
std::string_view method,
std::optional<folly::dynamic> params = std::nullopt);

/**
* Returns a JSON-formatted string representing a request.
*
* {"id": <id>, "method": <method>, "params": <params>}
*
* \param id Request ID.
* \param method Requested method.
* \param params Optional payload object.
*/
std::string jsonRequest(
RequestId id,
std::string_view method,
std::optional<folly::dynamic> params = std::nullopt);

} // namespace facebook::react::jsinspector_modern::cdp
30 changes: 30 additions & 0 deletions packages/react-native/ReactCommon/jsinspector-modern/HostAgent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,22 @@ void HostAgent::handleRequest(const cdp::PreparsedRequest& req) {
: std::nullopt,
});

shouldSendOKResponse = true;
isFinishedHandlingRequest = true;
} else if (req.method == "Overlay.setPausedInDebuggerMessage") {
auto message = req.params.isObject() && req.params.count("message")
? std::optional(req.params.at("message").asString())
: std::nullopt;
if (!isPausedInDebuggerOverlayVisible_ && message.has_value()) {
targetController_.incrementPauseOverlayCounter();
} else if (isPausedInDebuggerOverlayVisible_ && !message.has_value()) {
targetController_.decrementPauseOverlayCounter();
}
isPausedInDebuggerOverlayVisible_ = message.has_value();
targetController_.getDelegate().onSetPausedInDebuggerMessage({
.message = message,
});

shouldSendOKResponse = true;
isFinishedHandlingRequest = true;
} else if (req.method == "FuseboxClient.setClientMetadata") {
Expand Down Expand Up @@ -154,6 +170,20 @@ void HostAgent::handleRequest(const cdp::PreparsedRequest& req) {
req.method + " not implemented yet"));
}

HostAgent::~HostAgent() {
if (isPausedInDebuggerOverlayVisible_) {
// In case of a non-graceful shutdown of the session, ensure we clean up
// the "paused on debugger" overlay if we've previously asked the
// integrator to display it.
isPausedInDebuggerOverlayVisible_ = false;
if (!targetController_.decrementPauseOverlayCounter()) {
targetController_.getDelegate().onSetPausedInDebuggerMessage({
.message = std::nullopt,
});
}
}
}

void HostAgent::sendFuseboxNotice() {
static constexpr auto kFuseboxNotice = ANSI_COLOR_BG_YELLOW
"Welcome to the new React Native debugger (codename " ANSI_WEIGHT_BOLD
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ class HostAgent final {
HostTarget::SessionMetadata sessionMetadata,
SessionState& sessionState);

HostAgent(const HostAgent&) = delete;
HostAgent(HostAgent&&) = delete;
HostAgent& operator=(const HostAgent&) = delete;
HostAgent& operator=(HostAgent&&) = delete;

~HostAgent();

/**
* Handle a CDP request. The response will be sent over the provided
* \c FrontendChannel synchronously or asynchronously.
Expand Down Expand Up @@ -90,6 +97,7 @@ class HostAgent final {
const HostTarget::SessionMetadata sessionMetadata_;
std::shared_ptr<InstanceAgent> instanceAgent_;
FuseboxClientType fuseboxClientType_{FuseboxClientType::Unknown};
bool isPausedInDebuggerOverlayVisible_{false};

/**
* A shared reference to the session's state. This is only safe to access
Expand Down
Loading