diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/internal/bolts/Task.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/internal/bolts/Task.java index 5446df15cfc..7227380559e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/internal/bolts/Task.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/internal/bolts/Task.java @@ -8,6 +8,8 @@ package com.facebook.react.runtime.internal.bolts; import androidx.annotation.Nullable; +import com.facebook.infer.annotation.Assertions; +import com.facebook.infer.annotation.Nullsafe; import com.facebook.react.interfaces.TaskInterface; import java.util.ArrayList; import java.util.List; @@ -21,6 +23,7 @@ import java.util.concurrent.TimeUnit; * * @param The type of the result of the task. */ +@Nullsafe(Nullsafe.Mode.LOCAL) public class Task implements TaskInterface { /** * An {@link java.util.concurrent.Executor} that executes tasks in the current thread unless the @@ -75,18 +78,16 @@ public class Task implements TaskInterface { private final Object lock = new Object(); private boolean complete; private boolean cancelled; - // NULLSAFE_FIXME[Field Not Initialized] - private TResult result; - // NULLSAFE_FIXME[Field Not Initialized] - private Exception error; + + private @Nullable TResult result; + private @Nullable Exception error; private boolean errorHasBeenObserved; - // NULLSAFE_FIXME[Field Not Initialized] - private UnobservedErrorNotifier unobservedErrorNotifier; - private List> continuations = new ArrayList<>(); + private @Nullable UnobservedErrorNotifier unobservedErrorNotifier; + private @Nullable List> continuations = new ArrayList<>(); /* package */ Task() {} - private Task(TResult result) { + private Task(@Nullable TResult result) { trySetResult(result); } @@ -94,7 +95,6 @@ public class Task implements TaskInterface { if (cancelled) { trySetCancelled(); } else { - // NULLSAFE_FIXME[Parameter Not Nullable] trySetResult(null); } } @@ -139,7 +139,7 @@ public class Task implements TaskInterface { * @return The result of the task, if set. {@code null} otherwise. */ @Override - public TResult getResult() { + public @Nullable TResult getResult() { synchronized (lock) { return result; } @@ -149,13 +149,12 @@ public class Task implements TaskInterface { * @return The error for the task, if set. {@code null} otherwise. */ @Override - public Exception getError() { + public @Nullable Exception getError() { synchronized (lock) { if (error != null) { errorHasBeenObserved = true; if (unobservedErrorNotifier != null) { unobservedErrorNotifier.setObserved(); - // NULLSAFE_FIXME[Field Not Nullable] unobservedErrorNotifier = null; } } @@ -180,10 +179,10 @@ public class Task implements TaskInterface { * false} otherwise. */ @Override - // NULLSAFE_FIXME[Inconsistent Subclass Parameter Annotation] - public boolean waitForCompletion(long duration, TimeUnit timeUnit) throws InterruptedException { + public boolean waitForCompletion(long duration, @Nullable TimeUnit timeUnit) + throws InterruptedException { synchronized (lock) { - if (!isCompleted()) { + if (!isCompleted() && timeUnit != null) { lock.wait(timeUnit.toMillis(duration)); } return isCompleted(); @@ -227,6 +226,7 @@ public class Task implements TaskInterface { return Task.cancelled(); } if (task.isFaulted()) { + Assertions.assertNotNull(task.getError()); return Task.forError(task.getError()); } return Task.forResult(null); @@ -270,6 +270,7 @@ public class Task implements TaskInterface { synchronized (lock) { completed = this.isCompleted(); if (!completed) { + Assertions.assertNotNull(continuations); continuations.add( new Continuation() { @Override @@ -307,6 +308,7 @@ public class Task implements TaskInterface { synchronized (lock) { completed = this.isCompleted(); if (!completed) { + Assertions.assertNotNull(continuations); continuations.add( new Continuation() { @Override @@ -343,6 +345,7 @@ public class Task implements TaskInterface { @Override public Task then(Task task) { if (task.isFaulted()) { + Assertions.assertNotNull(task.getError()); return Task.forError(task.getError()); } else if (task.isCancelled()) { return Task.cancelled(); @@ -374,6 +377,7 @@ public class Task implements TaskInterface { @Override public Task then(Task task) { if (task.isFaulted()) { + Assertions.assertNotNull(task.getError()); return Task.forError(task.getError()); } else if (task.isCancelled()) { return Task.cancelled(); @@ -464,6 +468,7 @@ public class Task implements TaskInterface { if (task.isCancelled()) { tcs.setCancelled(); } else if (task.isFaulted()) { + Assertions.assertNotNull(task.getError()); tcs.setError(task.getError()); } else { tcs.setResult(task.getResult()); @@ -486,6 +491,7 @@ public class Task implements TaskInterface { private void runContinuations() { synchronized (lock) { + Assertions.assertNotNull(continuations); for (Continuation continuation : continuations) { try { continuation.then(this); @@ -495,7 +501,7 @@ public class Task implements TaskInterface { throw new RuntimeException(e); } } - // NULLSAFE_FIXME[Field Not Nullable] + // only setting continuations to null in siutations where complete is set to true continuations = null; } } @@ -515,7 +521,7 @@ public class Task implements TaskInterface { } /** Sets the result on the Task if the Task hasn't already been completed. */ - /* package */ boolean trySetResult(TResult result) { + /* package */ boolean trySetResult(@Nullable TResult result) { synchronized (lock) { if (complete) { return false; @@ -545,7 +551,6 @@ public class Task implements TaskInterface { } } - // NULLSAFE_FIXME[Parameter Not Nullable] private static Task TASK_NULL = new Task<>(null); private static Task TASK_TRUE = new Task<>((Boolean) true); private static Task TASK_FALSE = new Task<>((Boolean) false); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/internal/bolts/TaskCompletionSource.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/internal/bolts/TaskCompletionSource.kt index 4677e2f7819..c11b20161a5 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/internal/bolts/TaskCompletionSource.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/internal/bolts/TaskCompletionSource.kt @@ -25,7 +25,7 @@ internal class TaskCompletionSource() { fun trySetResult(result: TResult?): Boolean = task.trySetResult(result) /** Sets the error on the Task if the Task hasn't already been completed. */ - fun trySetError(error: Exception?): Boolean = task.trySetError(error) + fun trySetError(error: Exception): Boolean = task.trySetError(error) /** Sets the cancelled flag on the task, throwing if the Task has already been completed. */ fun setCancelled(): Unit { @@ -42,7 +42,7 @@ internal class TaskCompletionSource() { } /** Sets the error of the Task, throwing if the Task has already been completed. */ - fun setError(error: Exception?): Unit { + fun setError(error: Exception): Unit { if (!trySetError(error)) { throw IllegalStateException("Cannot set the error on a completed task.") }