diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.java index ccb10de08c3d9b..dd2652115500bf 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.java @@ -10,6 +10,7 @@ import android.os.Handler; import android.os.Looper; import androidx.annotation.Nullable; +import com.facebook.infer.annotation.Nullsafe; import com.facebook.jni.HybridData; import com.facebook.proguard.annotations.DoNotStrip; import java.io.Closeable; @@ -21,7 +22,8 @@ import okhttp3.WebSocketListener; /** Java wrapper around a C++ InspectorPackagerConnection. */ -/* package */ class CxxInspectorPackagerConnection implements IInspectorPackagerConnection { +/* package */ @Nullsafe(Nullsafe.Mode.LOCAL) +class CxxInspectorPackagerConnection implements IInspectorPackagerConnection { static { DevSupportSoLoader.staticInit(); } @@ -39,7 +41,7 @@ private static native HybridData initHybrid( public native void closeQuietly(); - public native void sendEventToAllConnections(String event); + public native void sendEventToAllConnections(@Nullable String event); /** Java wrapper around a C++ IWebSocketDelegate, allowing us to call the interface from Java. */ @DoNotStrip diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.java index 421377f7adaf24..9db6ef475fb916 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.java @@ -18,6 +18,7 @@ import android.widget.FrameLayout; import androidx.annotation.Nullable; import com.facebook.common.logging.FLog; +import com.facebook.infer.annotation.Nullsafe; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.common.ReactConstants; @@ -26,7 +27,8 @@ * Helper class for controlling overlay view with FPS and JS FPS info that gets added directly * to @{link WindowManager} instance. */ -/* package */ class DebugOverlayController { +/* package */ @Nullsafe(Nullsafe.Mode.LOCAL) +class DebugOverlayController { public static void requestPermission(Context context) { // Get permission to show debug overlay in dev builds. @@ -57,6 +59,7 @@ private static boolean hasPermission(Context context, String permission) { PackageInfo info = context .getPackageManager() + // NULLSAFE_FIXME[Nullable Dereference] .getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS); if (info.requestedPermissions != null) { for (String p : info.requestedPermissions) { @@ -73,7 +76,7 @@ private static boolean hasPermission(Context context, String permission) { private static boolean canHandleIntent(Context context, Intent intent) { PackageManager packageManager = context.getPackageManager(); - return intent.resolveActivity(packageManager) != null; + return packageManager != null && intent.resolveActivity(packageManager) != null; } private final WindowManager mWindowManager; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java index 155e45578b5b73..5411029777aaa2 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java @@ -15,6 +15,7 @@ import androidx.annotation.Nullable; import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; +import com.facebook.infer.annotation.Nullsafe; import com.facebook.react.bridge.ReactContext; import com.facebook.react.common.ReactConstants; import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener; @@ -59,6 +60,7 @@ *
JS traces return the full path to the file here, while Java traces only return the file * name (the path is not known). */ - public String getFile() { + @Override + public @Nullable String getFile() { return mFile; } @@ -109,7 +115,8 @@ public int getColumn() { *
For JS traces this is different from {@link #getFile()} in that it only returns the file
* name, not the full path. For Java traces there is no difference.
*/
- public String getFileName() {
+ @Override
+ public @Nullable String getFileName() {
return mFileName;
}
@@ -119,9 +126,10 @@ public boolean isCollapsed() {
/** Convert the stack frame to a JSON representation. */
public JSONObject toJSON() {
+ String file = getFile();
return new JSONObject(
MapBuilder.of(
- "file", getFile(),
+ "file", (file == null) ? "" : file,
"methodName", getMethod(),
"lineNumber", getLine(),
"column", getColumn(),
@@ -136,25 +144,33 @@ public JSONObject toJSON() {
public static StackFrame[] convertJsStackTrace(@Nullable ReadableArray stack) {
int size = stack != null ? stack.size() : 0;
StackFrame[] result = new StackFrame[size];
- for (int i = 0; i < size; i++) {
- ReadableType type = stack.getType(i);
- if (type == ReadableType.Map) {
- ReadableMap frame = stack.getMap(i);
- String methodName = frame.getString("methodName");
- String fileName = frame.getString("file");
- boolean collapse =
- frame.hasKey("collapse") && !frame.isNull("collapse") && frame.getBoolean("collapse");
- int lineNumber = -1;
- if (frame.hasKey(LINE_NUMBER_KEY) && !frame.isNull(LINE_NUMBER_KEY)) {
- lineNumber = frame.getInt(LINE_NUMBER_KEY);
- }
- int columnNumber = -1;
- if (frame.hasKey(COLUMN_KEY) && !frame.isNull(COLUMN_KEY)) {
- columnNumber = frame.getInt(COLUMN_KEY);
+ if (stack != null) {
+ for (int i = 0; i < size; i++) {
+ ReadableType type = stack.getType(i);
+ if (type == ReadableType.Map) {
+ ReadableMap frame = stack.getMap(i);
+ Assertions.assertNotNull(frame);
+ String methodName = frame.getString("methodName");
+ String fileName = frame.getString("file");
+ Assertions.assertNotNull(fileName);
+ Assertions.assertNotNull(methodName);
+ boolean collapse =
+ frame.hasKey("collapse") && !frame.isNull("collapse") && frame.getBoolean("collapse");
+ int lineNumber = -1;
+ if (frame.hasKey(LINE_NUMBER_KEY) && !frame.isNull(LINE_NUMBER_KEY)) {
+ lineNumber = frame.getInt(LINE_NUMBER_KEY);
+ }
+ int columnNumber = -1;
+ if (frame.hasKey(COLUMN_KEY) && !frame.isNull(COLUMN_KEY)) {
+ columnNumber = frame.getInt(COLUMN_KEY);
+ }
+ result[i] = new StackFrameImpl(fileName, methodName, lineNumber, columnNumber, collapse);
+ } else if (type == ReadableType.String) {
+ String stackFrame = stack.getString(i);
+ if (stackFrame != null) {
+ result[i] = new StackFrameImpl(null, stackFrame, -1, -1);
+ }
}
- result[i] = new StackFrameImpl(fileName, methodName, lineNumber, columnNumber, collapse);
- } else if (type == ReadableType.String) {
- result[i] = new StackFrameImpl(null, stack.getString(i), -1, -1);
}
}
return result;
@@ -203,15 +219,22 @@ public static StackFrame[] convertJsStackTrace(String stack) {
} else if (matcher1.find()) {
matcher = matcher1;
} else {
- result[i] = new StackFrameImpl(null, stackTrace[i], -1, -1);
+ String unmatchedStackFrame = stackTrace[i];
+ if (unmatchedStackFrame != null) {
+ result[i] = new StackFrameImpl(null, unmatchedStackFrame, -1, -1);
+ }
+ continue;
+ }
+ String fileName = matcher.group(2);
+ String methodName = matcher.group(1) == null ? "(unknown)" : matcher.group(1);
+ String lineString = matcher.group(3);
+ String columnString = matcher.group(4);
+ if (methodName == null || fileName == null || lineString == null || columnString == null) {
continue;
}
result[i] =
new StackFrameImpl(
- matcher.group(2),
- matcher.group(1) == null ? "(unknown)" : matcher.group(1),
- Integer.parseInt(matcher.group(3)),
- Integer.parseInt(matcher.group(4)));
+ fileName, methodName, Integer.parseInt(lineString), Integer.parseInt(columnString));
}
return result;
}
diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/StackFrame.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/StackFrame.kt
index 47f32567879a0f..8f462ae6171bae 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/StackFrame.kt
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/StackFrame.kt
@@ -20,7 +20,7 @@ public interface StackFrame {
public val file: String?
/** Get the name of the method this frame points to. */
- public val method: String?
+ public val method: String
/** Get the line number this frame points to in the file returned by [.getFile]. */
public val line: Int
@@ -40,5 +40,5 @@ public interface StackFrame {
public val isCollapsed: Boolean
/** Convert the stack frame to a JSON representation. */
- public fun toJSON(): JSONObject?
+ public fun toJSON(): JSONObject
}
diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/JSDebuggerWebSocketClientTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/JSDebuggerWebSocketClientTest.kt
index fbef2c7dc9e1b7..bcec632eb6250e 100644
--- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/JSDebuggerWebSocketClientTest.kt
+++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/JSDebuggerWebSocketClientTest.kt
@@ -41,7 +41,7 @@ class JSDebuggerWebSocketClientTest {
val client = spy(JSDebuggerWebSocketClient())
val injectedObjects = mapOf("key1" to "value1", "key2" to "value2")
client.loadBundle(
- "http://localhost:8080/index.js", injectedObjects as HashMap