Java CxxInspectorPackagerConnection (#42018)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/42018

Creates an JNI wrapper around the C++ version of `InspectorPackagerConnection` (introduced in D52134592), and uses it in React Native Android apps (behind an internal flag that is off by default).

In future work, the flag will be turned on by default, then deleted, and eventually the legacy `InspectorPackagerConnection.java` code will be deleted from React Native.

Changelog: [Internal]

Reviewed By: huntie

Differential Revision: D52231237

fbshipit-source-id: 5a0e3bd8b2b711c1c592db15c51df4c3cc89aaad
This commit is contained in:
Moti Zilberman
2024-01-09 10:11:41 -08:00
committed by Facebook GitHub Bot
parent aa2d613cfa
commit a9a736f2ad
23 changed files with 764 additions and 5 deletions
@@ -733,6 +733,7 @@ public abstract interface class com/facebook/react/bridge/Inspector$RemoteConnec
}
public class com/facebook/react/bridge/InspectorFlags {
public static fun getEnableCxxInspectorPackagerConnection ()Z
public static fun getEnableModernCDPRegistry ()Z
}
@@ -2197,7 +2198,7 @@ public abstract interface class com/facebook/react/devsupport/HMRClient : com/fa
public abstract fun setup (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZ)V
}
public class com/facebook/react/devsupport/InspectorPackagerConnection {
public class com/facebook/react/devsupport/InspectorPackagerConnection : com/facebook/react/devsupport/IInspectorPackagerConnection {
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
public fun closeQuietly ()V
public fun connect ()V
@@ -524,6 +524,7 @@ android {
"hermesinstancejni",
"uimanagerjni",
"jscinstance",
"react_devsupportjni",
// prefab targets
"reactnativejni",
"react_render_debug",
@@ -19,5 +19,8 @@ public class InspectorFlags {
@DoNotStrip
public static native boolean getEnableModernCDPRegistry();
@DoNotStrip
public static native boolean getEnableCxxInspectorPackagerConnection();
private InspectorFlags() {}
}
@@ -0,0 +1,142 @@
/*
* 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.
*/
package com.facebook.react.devsupport;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.Nullable;
import com.facebook.jni.HybridData;
import com.facebook.proguard.annotations.DoNotStrip;
import java.io.Closeable;
import java.util.OptionalInt;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
/** Java wrapper around a C++ InspectorPackagerConnection. */
/* package */ class CxxInspectorPackagerConnection implements IInspectorPackagerConnection {
static {
DevSupportSoLoader.staticInit();
}
@DoNotStrip private final HybridData mHybridData;
public CxxInspectorPackagerConnection(String url, String packageName) {
mHybridData = initHybrid(url, packageName, new DelegateImpl());
}
private static native HybridData initHybrid(
String url, String packageName, DelegateImpl delegate);
public native void connect();
public native void closeQuietly();
public native void sendEventToAllConnections(String event);
/** Java wrapper around a C++ IWebSocketDelegate, allowing us to call the interface from Java. */
@DoNotStrip
private static class WebSocketDelegate implements Closeable {
private final HybridData mHybridData;
public native void didFailWithError(OptionalInt posixCode, String error);
public native void didReceiveMessage(String message);
public native void didClose();
/**
* Release the C++ part of the hybrid WebSocketDelegate object. This should be called when the
* delegate is not needed anymore ( = the socket will not send more events).
*/
@Override
public void close() {
mHybridData.resetNative();
}
@DoNotStrip
private WebSocketDelegate(HybridData hybridData) {
mHybridData = hybridData;
}
}
/**
* Java counterpart of the C++ IWebSocket interface, allowing us to implement the interface in
* Java.
*/
private interface IWebSocket extends Closeable {
void send(String message);
/**
* Close the WebSocket connection. NOTE: There is no close() method in the C++ interface.
* Instead, this method is called when the IWebSocket is destroyed on the C++ side.
*/
void close();
}
/** Java implementation of the C++ InspectorPackagerConnectionDelegate interface. */
private static class DelegateImpl {
private final OkHttpClient mHttpClient =
new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(0, TimeUnit.MINUTES) // Disable timeouts for read
.build();
private final Handler mHandler = new Handler(Looper.getMainLooper());
public IWebSocket connectWebSocket(String url, WebSocketDelegate delegate) {
Request request = new Request.Builder().url(url).build();
final WebSocket webSocket =
mHttpClient.newWebSocket(
request,
new WebSocketListener() {
@Override
public void onFailure(WebSocket _unused, Throwable t, @Nullable Response response) {
@Nullable String message = t.getMessage();
delegate.didFailWithError(
OptionalInt.empty(), message != null ? message : "<Unknown error>");
// "No further calls to this listener will be made." -OkHttp docs for
// WebSocketListener.onFailure
delegate.close();
}
@Override
public void onMessage(WebSocket _unused, String text) {
delegate.didReceiveMessage(text);
}
@Override
public void onClosed(WebSocket _unused, int code, String reason) {
delegate.didClose();
// "No further calls to this listener will be made." -OkHttp docs for
// WebSocketListener.onClosed
delegate.close();
}
});
return new IWebSocket() {
@Override
public void send(String message) {
webSocket.send(message);
}
@Override
public void close() {
webSocket.close(1000, "End of session");
}
};
}
public void scheduleCallback(Runnable runnable, long delayMs) {
mHandler.postDelayed(runnable, delayMs);
}
}
}
@@ -14,6 +14,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.facebook.common.logging.FLog;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.InspectorFlags;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
@@ -107,7 +108,7 @@ public class DevServerHelper {
private final String mPackageName;
private @Nullable JSPackagerClient mPackagerClient;
private @Nullable InspectorPackagerConnection mInspectorPackagerConnection;
private @Nullable IInspectorPackagerConnection mInspectorPackagerConnection;
public DevServerHelper(
DeveloperSettings developerSettings,
@@ -210,8 +211,13 @@ public class DevServerHelper {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
mInspectorPackagerConnection =
new InspectorPackagerConnection(getInspectorDeviceUrl(), mPackageName);
if (InspectorFlags.getEnableCxxInspectorPackagerConnection()) {
mInspectorPackagerConnection =
new CxxInspectorPackagerConnection(getInspectorDeviceUrl(), mPackageName);
} else {
mInspectorPackagerConnection =
new InspectorPackagerConnection(getInspectorDeviceUrl(), mPackageName);
}
mInspectorPackagerConnection.connect();
return null;
}
@@ -0,0 +1,22 @@
/*
* 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.
*/
package com.facebook.react.devsupport;
import com.facebook.soloader.SoLoader;
class DevSupportSoLoader {
private static volatile boolean sDidInit = false;
public static synchronized void staticInit() {
if (sDidInit) {
return;
}
SoLoader.loadLibrary("react_devsupportjni");
sDidInit = true;
}
}
@@ -0,0 +1,16 @@
/*
* 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.
*/
package com.facebook.react.devsupport;
/* package */ interface IInspectorPackagerConnection {
public void connect();
public void closeQuietly();
public void sendEventToAllConnections(String event);
}
@@ -27,7 +27,7 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class InspectorPackagerConnection {
public class InspectorPackagerConnection implements IInspectorPackagerConnection {
private static final String TAG = "InspectorPackagerConnection";
private final Connection mConnection;
@@ -125,6 +125,7 @@ add_react_android_subdir(src/main/jni/react/runtime/cxxreactpackage)
add_react_android_subdir(src/main/jni/react/runtime/jni)
add_react_android_subdir(src/main/jni/react/runtime/hermes/jni)
add_react_android_subdir(src/main/jni/react/runtime/jsc/jni)
add_react_android_subdir(src/main/jni/react/devsupport)
# GTest dependencies
add_executable(reactnative_unittest
@@ -0,0 +1,19 @@
# 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.
cmake_minimum_required(VERSION 3.13)
set(CMAKE_VERBOSE_MAKEFILE on)
add_compile_options(-fexceptions -frtti -std=c++20 -Wall -DLOG_TAG=\"ReactNative\")
file(GLOB react_devsupportjni_SRC CONFIGURE_DEPENDS *.cpp)
add_library(react_devsupportjni SHARED ${react_devsupportjni_SRC})
target_include_directories(react_devsupportjni PUBLIC .)
target_link_libraries(react_devsupportjni
fbjni
jsinspector)
@@ -0,0 +1,55 @@
/*
* 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.
*/
#include "JCxxInspectorPackagerConnection.h"
#include <fbjni/NativeRunnable.h>
using namespace facebook::jni;
namespace facebook::react::jsinspector_modern {
JCxxInspectorPackagerConnection::JCxxInspectorPackagerConnection(
const std::string& url,
const std::string& packageName,
alias_ref<JDelegateImpl::javaobject> delegate)
: cxxImpl_(url, packageName, delegate->wrapInUniquePtr()) {}
local_ref<JCxxInspectorPackagerConnection::jhybriddata>
JCxxInspectorPackagerConnection::initHybrid(
alias_ref<jclass>,
const std::string& url,
const std::string& packageName,
alias_ref<JDelegateImpl::javaobject> delegate) {
return makeCxxInstance(url, packageName, delegate);
}
void JCxxInspectorPackagerConnection::connect() {
cxxImpl_.connect();
}
void JCxxInspectorPackagerConnection::closeQuietly() {
cxxImpl_.closeQuietly();
}
void JCxxInspectorPackagerConnection::sendEventToAllConnections(
const std::string& event) {
cxxImpl_.sendEventToAllConnections(event);
}
void JCxxInspectorPackagerConnection::registerNatives() {
registerHybrid(
{makeNativeMethod(
"initHybrid", JCxxInspectorPackagerConnection::initHybrid),
makeNativeMethod("connect", JCxxInspectorPackagerConnection::connect),
makeNativeMethod(
"closeQuietly", JCxxInspectorPackagerConnection::closeQuietly),
makeNativeMethod(
"sendEventToAllConnections",
JCxxInspectorPackagerConnection::sendEventToAllConnections)});
}
} // namespace facebook::react::jsinspector_modern
@@ -0,0 +1,62 @@
/*
* 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 "JCxxInspectorPackagerConnectionDelegateImpl.h"
#include <fbjni/fbjni.h>
#include <jsinspector-modern/InspectorPackagerConnection.h>
#include <string>
namespace facebook::react::jsinspector_modern {
/**
* A hybrid Java/C++ class that exposes an instance of
* InspectorPackagerConnection to Java.
*/
class JCxxInspectorPackagerConnection
: public jni::HybridClass<JCxxInspectorPackagerConnection> {
public:
constexpr static auto kJavaDescriptor =
"Lcom/facebook/react/devsupport/CxxInspectorPackagerConnection;";
static void registerNatives();
// InspectorPackagerConnection's public API
void connect();
void closeQuietly();
void sendEventToAllConnections(const std::string& event);
private:
friend HybridBase;
using JDelegateImpl = JCxxInspectorPackagerConnectionDelegateImpl;
/**
* Private constructor since this class can only be created from Java.
*/
JCxxInspectorPackagerConnection(
const std::string& url,
const std::string& packageName,
jni::alias_ref<JDelegateImpl::javaobject> delegate);
static jni::local_ref<jhybriddata> initHybrid(
jni::alias_ref<jclass>,
const std::string& url,
const std::string& packageName,
jni::alias_ref<JDelegateImpl::javaobject> delegate);
/**
* The actual C++ implementation wrapped by this hybrid class.
*/
InspectorPackagerConnection cxxImpl_;
};
} // namespace facebook::react::jsinspector_modern
@@ -0,0 +1,72 @@
/*
* 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.
*/
#include "JCxxInspectorPackagerConnectionDelegateImpl.h"
#include "JCxxInspectorPackagerConnectionWebSocket.h"
#include "JCxxInspectorPackagerConnectionWebSocketDelegate.h"
#include <fbjni/NativeRunnable.h>
#include <string>
using namespace facebook::jni;
namespace facebook::react::jsinspector_modern {
std::unique_ptr<IWebSocket>
JCxxInspectorPackagerConnectionDelegateImpl::connectWebSocket(
const std::string& url,
std::weak_ptr<IWebSocketDelegate> delegate) {
using JWebSocket = JCxxInspectorPackagerConnectionWebSocket;
using JWebSocketDelegate = JCxxInspectorPackagerConnectionWebSocketDelegate;
static auto method =
javaClassStatic()
->getMethod<alias_ref<JWebSocket::javaobject>(
const std::string&, alias_ref<JWebSocketDelegate::javaobject>)>(
"connectWebSocket");
auto jWebSocket = method(
self(), url, make_global(JWebSocketDelegate::newObjectCxxArgs(delegate)));
return jWebSocket->wrapInUniquePtr();
}
void JCxxInspectorPackagerConnectionDelegateImpl::scheduleCallback(
std::function<void(void)> callback,
std::chrono::milliseconds delayMs) {
static auto method =
javaClassStatic()
->getMethod<void(alias_ref<JRunnable::javaobject>, jlong)>(
"scheduleCallback");
method(
self(),
JNativeRunnable::newObjectCxxArgs(std::move(callback)),
static_cast<jlong>(delayMs.count()));
}
std::unique_ptr<InspectorPackagerConnectionDelegate>
JCxxInspectorPackagerConnectionDelegateImpl::wrapInUniquePtr() {
return std::unique_ptr<InspectorPackagerConnectionDelegate>{
new RefWrapper{self()}};
}
JCxxInspectorPackagerConnectionDelegateImpl::RefWrapper::RefWrapper(
jni::alias_ref<javaobject> jDelegate)
: jDelegate_(make_global(jDelegate)) {}
std::unique_ptr<IWebSocket>
JCxxInspectorPackagerConnectionDelegateImpl::RefWrapper::connectWebSocket(
const std::string& url,
std::weak_ptr<IWebSocketDelegate> delegate) {
return jDelegate_->connectWebSocket(url, delegate);
}
void JCxxInspectorPackagerConnectionDelegateImpl::RefWrapper::scheduleCallback(
std::function<void(void)> callback,
std::chrono::milliseconds delayMs) {
return jDelegate_->scheduleCallback(callback, delayMs);
}
} // namespace facebook::react::jsinspector_modern
@@ -0,0 +1,69 @@
/*
* 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 <fbjni/fbjni.h>
#include <jsinspector-modern/InspectorPackagerConnection.h>
#include <chrono>
#include <functional>
#include <memory>
#include <string>
namespace facebook::react::jsinspector_modern {
/**
* Exposes an instance of the Java class
* CxxInspectorPackagerConnection.DelegateImpl to C++. The public interface
* mirrors InspectorPackagerConnectionDelegate exactly but doesn't inherit from
* it; this is because of fbjni limitations on multiple inheritance. To get a
* usable InspectorPackagerConnectionDelegate instance from this object, call
* wrapInUniquePtr().
*/
struct JCxxInspectorPackagerConnectionDelegateImpl
: public jni::JavaClass<JCxxInspectorPackagerConnectionDelegateImpl> {
public:
static auto constexpr kJavaDescriptor =
"Lcom/facebook/react/devsupport/CxxInspectorPackagerConnection$DelegateImpl;";
std::unique_ptr<InspectorPackagerConnectionDelegate> wrapInUniquePtr();
// InspectorPackagerConnectionDelegate methods (mirrored)
std::unique_ptr<IWebSocket> connectWebSocket(
const std::string& url,
std::weak_ptr<IWebSocketDelegate> delegate);
void scheduleCallback(
std::function<void(void)> callback,
std::chrono::milliseconds delayMs);
private:
class RefWrapper;
};
class JCxxInspectorPackagerConnectionDelegateImpl::RefWrapper
: public InspectorPackagerConnectionDelegate {
public:
explicit RefWrapper(jni::alias_ref<javaobject> jDelegate);
// InspectorPackagerConnectionDelegate methods
virtual std::unique_ptr<IWebSocket> connectWebSocket(
const std::string& url,
std::weak_ptr<IWebSocketDelegate> delegate) override;
virtual void scheduleCallback(
std::function<void(void)> callback,
std::chrono::milliseconds delayMs) override;
private:
jni::global_ref<javaobject> jDelegate_;
};
} // namespace facebook::react::jsinspector_modern
@@ -0,0 +1,45 @@
/*
* 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.
*/
#include "JCxxInspectorPackagerConnectionWebSocket.h"
using namespace facebook::jni;
using namespace facebook::react::jsinspector_modern;
namespace facebook::react::jsinspector_modern {
void JCxxInspectorPackagerConnectionWebSocket::send(std::string_view message) {
static auto method =
javaClassStatic()->getMethod<void(const std::string&)>("send");
method(self(), std::string(message));
}
void JCxxInspectorPackagerConnectionWebSocket::close() {
static auto method = javaClassStatic()->getMethod<void()>("close");
method(self());
}
JCxxInspectorPackagerConnectionWebSocket::
~JCxxInspectorPackagerConnectionWebSocket() {
close();
}
std::unique_ptr<IWebSocket>
JCxxInspectorPackagerConnectionWebSocket::wrapInUniquePtr() {
return std::make_unique<RefWrapper>(self());
}
JCxxInspectorPackagerConnectionWebSocket::RefWrapper::RefWrapper(
alias_ref<javaobject> jWebSocket)
: jWebSocket_{make_global(jWebSocket)} {}
void JCxxInspectorPackagerConnectionWebSocket::RefWrapper::send(
std::string_view message) {
jWebSocket_->send(message);
}
} // namespace facebook::react::jsinspector_modern
@@ -0,0 +1,56 @@
/*
* 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 <fbjni/fbjni.h>
#include <jsinspector-modern/InspectorPackagerConnection.h>
#include <memory>
namespace facebook::react::jsinspector_modern {
/**
* Exposes an implementation of the Java interface
* CxxInspectorPackagerConnection.IWebSocket to C++. The public interface
* mirrors IWebSocket exactly but doesn't inherit from
* it; this is because of fbjni limitations on multiple inheritance. To get a
* usable IWebSocket instance from this object, call
* wrapInUniquePtr().
*/
class JCxxInspectorPackagerConnectionWebSocket
: public jni::JavaClass<JCxxInspectorPackagerConnectionWebSocket> {
public:
static auto constexpr kJavaDescriptor =
"Lcom/facebook/react/devsupport/CxxInspectorPackagerConnection$IWebSocket;";
~JCxxInspectorPackagerConnectionWebSocket();
std::unique_ptr<jsinspector_modern::IWebSocket> wrapInUniquePtr();
// IWebSocket methods (mirrored)
void send(std::string_view message);
private:
class RefWrapper;
void close();
};
class JCxxInspectorPackagerConnectionWebSocket::RefWrapper : public IWebSocket {
public:
explicit RefWrapper(jni::alias_ref<javaobject> jWebSocket_);
// IWebSocket methods
virtual void send(std::string_view message) override;
private:
jni::global_ref<javaobject> jWebSocket_;
};
} // namespace facebook::react::jsinspector_modern
@@ -0,0 +1,53 @@
/*
* 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.
*/
#include "JCxxInspectorPackagerConnectionWebSocketDelegate.h"
using namespace facebook::jni;
namespace facebook::react::jsinspector_modern {
JCxxInspectorPackagerConnectionWebSocketDelegate::
JCxxInspectorPackagerConnectionWebSocketDelegate(
std::weak_ptr<IWebSocketDelegate> cxxDelegate)
: cxxDelegate_(cxxDelegate) {}
void JCxxInspectorPackagerConnectionWebSocketDelegate::didFailWithError(
alias_ref<JOptionalInt::javaobject> posixCode,
const std::string& error) {
if (auto delegate = cxxDelegate_.lock()) {
delegate->didFailWithError(*posixCode, error);
}
}
void JCxxInspectorPackagerConnectionWebSocketDelegate::didReceiveMessage(
const std::string& message) {
if (auto delegate = cxxDelegate_.lock()) {
delegate->didReceiveMessage(message);
}
}
void JCxxInspectorPackagerConnectionWebSocketDelegate::didClose() {
if (auto delegate = cxxDelegate_.lock()) {
delegate->didClose();
}
}
void JCxxInspectorPackagerConnectionWebSocketDelegate::registerNatives() {
registerHybrid(
{makeNativeMethod(
"didFailWithError",
JCxxInspectorPackagerConnectionWebSocketDelegate::didFailWithError),
makeNativeMethod(
"didReceiveMessage",
JCxxInspectorPackagerConnectionWebSocketDelegate::didReceiveMessage),
makeNativeMethod(
"didClose",
JCxxInspectorPackagerConnectionWebSocketDelegate::didClose)});
}
} // namespace facebook::react::jsinspector_modern
@@ -0,0 +1,49 @@
/*
* 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 "JOptional.h"
#include <fbjni/fbjni.h>
#include <jsinspector-modern/InspectorPackagerConnection.h>
#include <memory>
#include <string>
namespace facebook::react::jsinspector_modern {
/**
* A hybrid Java/C++ class that exposes a C++ implementation of
* IWebSocketDelegate to Java.
*/
class JCxxInspectorPackagerConnectionWebSocketDelegate
: public jni::HybridClass<
JCxxInspectorPackagerConnectionWebSocketDelegate> {
public:
static auto constexpr kJavaDescriptor =
"Lcom/facebook/react/devsupport/CxxInspectorPackagerConnection$WebSocketDelegate;";
void didFailWithError(
jni::alias_ref<JOptionalInt::javaobject> posixCode,
const std::string& error);
void didReceiveMessage(const std::string& message);
void didClose();
static void registerNatives();
JCxxInspectorPackagerConnectionWebSocketDelegate(
std::weak_ptr<IWebSocketDelegate> cxxDelegate);
private:
friend HybridBase;
std::weak_ptr<IWebSocketDelegate> cxxDelegate_;
};
} // namespace facebook::react::jsinspector_modern
@@ -0,0 +1,29 @@
/*
* 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.
*/
#include "JOptional.h"
namespace facebook::react {
int JOptionalInt::getAsInt() const {
static auto method = javaClassStatic()->getMethod<jint()>("getAsInt");
return method(self());
}
bool JOptionalInt::isPresent() const {
static auto method = javaClassStatic()->getMethod<jboolean()>("isPresent");
return method(self());
}
JOptionalInt::operator std::optional<int>() const {
if (!isPresent()) {
return {};
}
return getAsInt();
}
} // namespace facebook::react
@@ -0,0 +1,27 @@
/*
* 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 <fbjni/fbjni.h>
#include <optional>
// TODO(moti): Consider moving this into fbjni
namespace facebook::react {
class JOptionalInt : public facebook::jni::JavaClass<JOptionalInt> {
public:
static auto constexpr kJavaDescriptor = "Ljava/util/OptionalInt;";
int getAsInt() const;
bool isPresent() const;
operator std::optional<int>() const;
};
} // namespace facebook::react
@@ -0,0 +1,20 @@
/*
* 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.
*/
#include "JCxxInspectorPackagerConnection.h"
#include "JCxxInspectorPackagerConnectionWebSocketDelegate.h"
#include <fbjni/fbjni.h>
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
return facebook::jni::initialize(vm, [] {
facebook::react::jsinspector_modern::JCxxInspectorPackagerConnection::
registerNatives();
facebook::react::jsinspector_modern::
JCxxInspectorPackagerConnectionWebSocketDelegate::registerNatives();
});
}
@@ -16,11 +16,20 @@ bool JInspectorFlags::getEnableModernCDPRegistry(jni::alias_ref<jclass>) {
return inspectorFlags.getEnableModernCDPRegistry();
}
bool JInspectorFlags::getEnableCxxInspectorPackagerConnection(
jni::alias_ref<jclass>) {
auto& inspectorFlags = jsinspector_modern::InspectorFlags::getInstance();
return inspectorFlags.getEnableCxxInspectorPackagerConnection();
}
void JInspectorFlags::registerNatives() {
javaClassLocal()->registerNatives({
makeNativeMethod(
"getEnableModernCDPRegistry",
JInspectorFlags::getEnableModernCDPRegistry),
makeNativeMethod(
"getEnableCxxInspectorPackagerConnection",
JInspectorFlags::getEnableCxxInspectorPackagerConnection),
});
}
@@ -21,6 +21,8 @@ class JInspectorFlags : public jni::JavaClass<JInspectorFlags> {
static bool getEnableModernCDPRegistry(jni::alias_ref<jclass>);
static bool getEnableCxxInspectorPackagerConnection(jni::alias_ref<jclass>);
static void registerNatives();
private: