mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Prepare bolts to be safe to use it from Kotlin
Summary: In this diff I analyzed bolts library to ensure it's ready to be used from kotlin. I won't convert bolts to kotlin, but this is necessary to be able to convert its callsites (ReactHost) to kotlin bypass-github-export-checks changelog: [internal] internal Reviewed By: fkgozali Differential Revision: D46194127 fbshipit-source-id: 609e356230b1c87fe26571b811d23430d0168276
This commit is contained in:
committed by
Facebook GitHub Bot
parent
88eef42cab
commit
dfb42a3946
+14
-10
@@ -7,6 +7,8 @@
|
||||
|
||||
package com.facebook.react.bridgeless.internal.bolts;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
@@ -24,7 +26,7 @@ public class AggregateException extends Exception {
|
||||
|
||||
private static final String DEFAULT_MESSAGE = "There were multiple errors.";
|
||||
|
||||
private List<Throwable> innerThrowables;
|
||||
@NonNull private final List<Throwable> innerThrowables;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code AggregateException} with the current stack trace, the specified detail
|
||||
@@ -33,7 +35,7 @@ public class AggregateException extends Exception {
|
||||
* @param detailMessage The detail message for this exception.
|
||||
* @param innerThrowables The exceptions that are the cause of the current exception.
|
||||
*/
|
||||
public AggregateException(String detailMessage, Throwable[] innerThrowables) {
|
||||
public AggregateException(@NonNull String detailMessage, @NonNull Throwable[] innerThrowables) {
|
||||
this(detailMessage, Arrays.asList(innerThrowables));
|
||||
}
|
||||
|
||||
@@ -44,11 +46,13 @@ public class AggregateException extends Exception {
|
||||
* @param detailMessage The detail message for this exception.
|
||||
* @param innerThrowables The exceptions that are the cause of the current exception.
|
||||
*/
|
||||
public AggregateException(String detailMessage, List<? extends Throwable> innerThrowables) {
|
||||
public AggregateException(
|
||||
@NonNull String detailMessage, @Nullable List<? extends Throwable> innerThrowables) {
|
||||
super(
|
||||
detailMessage,
|
||||
innerThrowables != null && innerThrowables.size() > 0 ? innerThrowables.get(0) : null);
|
||||
this.innerThrowables = Collections.unmodifiableList(innerThrowables);
|
||||
this.innerThrowables =
|
||||
Collections.unmodifiableList(innerThrowables != null ? innerThrowables : new ArrayList<>());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,7 +61,7 @@ public class AggregateException extends Exception {
|
||||
*
|
||||
* @param innerThrowables The exceptions that are the cause of the current exception.
|
||||
*/
|
||||
public AggregateException(List<? extends Throwable> innerThrowables) {
|
||||
public AggregateException(@Nullable List<? extends Throwable> innerThrowables) {
|
||||
this(DEFAULT_MESSAGE, innerThrowables);
|
||||
}
|
||||
|
||||
@@ -65,12 +69,12 @@ public class AggregateException extends Exception {
|
||||
* Returns a read-only {@link List} of the {@link Throwable} instances that caused the current
|
||||
* exception.
|
||||
*/
|
||||
public List<Throwable> getInnerThrowables() {
|
||||
public @NonNull List<Throwable> getInnerThrowables() {
|
||||
return innerThrowables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printStackTrace(PrintStream err) {
|
||||
public void printStackTrace(@NonNull PrintStream err) {
|
||||
super.printStackTrace(err);
|
||||
|
||||
int currentIndex = -1;
|
||||
@@ -85,7 +89,7 @@ public class AggregateException extends Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printStackTrace(PrintWriter err) {
|
||||
public void printStackTrace(@NonNull PrintWriter err) {
|
||||
super.printStackTrace(err);
|
||||
|
||||
int currentIndex = -1;
|
||||
@@ -101,7 +105,7 @@ public class AggregateException extends Exception {
|
||||
|
||||
/** @deprecated Please use {@link #getInnerThrowables()} instead. */
|
||||
@Deprecated
|
||||
public List<Exception> getErrors() {
|
||||
public @NonNull List<Exception> getErrors() {
|
||||
List<Exception> errors = new ArrayList<Exception>();
|
||||
if (innerThrowables == null) {
|
||||
return errors;
|
||||
@@ -119,7 +123,7 @@ public class AggregateException extends Exception {
|
||||
|
||||
/** @deprecated Please use {@link #getInnerThrowables()} instead. */
|
||||
@Deprecated
|
||||
public Throwable[] getCauses() {
|
||||
public @NonNull Throwable[] getCauses() {
|
||||
return innerThrowables.toArray(new Throwable[innerThrowables.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-7
@@ -11,6 +11,7 @@ import android.annotation.SuppressLint;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import androidx.annotation.NonNull;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
@@ -32,11 +33,12 @@ import java.util.concurrent.TimeUnit;
|
||||
* 0 and maxPoolSize is Integer.MAX_VALUE. This is dangerous because it can create an unchecked
|
||||
* amount of threads.
|
||||
*/
|
||||
/* package */ final class AndroidExecutors {
|
||||
/* package */
|
||||
final class AndroidExecutors {
|
||||
|
||||
private static final AndroidExecutors INSTANCE = new AndroidExecutors();
|
||||
|
||||
private final Executor uiThread;
|
||||
@NonNull private final Executor uiThread;
|
||||
|
||||
private AndroidExecutors() {
|
||||
uiThread = new UIThreadExecutor();
|
||||
@@ -64,7 +66,7 @@ import java.util.concurrent.TimeUnit;
|
||||
*
|
||||
* @return the newly created thread pool
|
||||
*/
|
||||
public static ExecutorService newCachedThreadPool() {
|
||||
public static @NonNull ExecutorService newCachedThreadPool() {
|
||||
ThreadPoolExecutor executor =
|
||||
new ThreadPoolExecutor(
|
||||
CORE_POOL_SIZE,
|
||||
@@ -89,7 +91,7 @@ import java.util.concurrent.TimeUnit;
|
||||
* @param threadFactory the factory to use when creating new threads
|
||||
* @return the newly created thread pool
|
||||
*/
|
||||
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
|
||||
public static @NonNull ExecutorService newCachedThreadPool(@NonNull ThreadFactory threadFactory) {
|
||||
ThreadPoolExecutor executor =
|
||||
new ThreadPoolExecutor(
|
||||
CORE_POOL_SIZE,
|
||||
@@ -114,21 +116,21 @@ import java.util.concurrent.TimeUnit;
|
||||
* @param value true if should time out, else false
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public static void allowCoreThreadTimeout(ThreadPoolExecutor executor, boolean value) {
|
||||
public static void allowCoreThreadTimeout(@NonNull ThreadPoolExecutor executor, boolean value) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
|
||||
executor.allowCoreThreadTimeOut(value);
|
||||
}
|
||||
}
|
||||
|
||||
/** An {@link java.util.concurrent.Executor} that executes tasks on the UI thread. */
|
||||
public static Executor uiThread() {
|
||||
public static @NonNull Executor uiThread() {
|
||||
return INSTANCE.uiThread;
|
||||
}
|
||||
|
||||
/** An {@link java.util.concurrent.Executor} that runs tasks on the UI thread. */
|
||||
private static class UIThreadExecutor implements Executor {
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
public void execute(@NonNull Runnable command) {
|
||||
new Handler(Looper.getMainLooper()).post(command);
|
||||
}
|
||||
}
|
||||
|
||||
+10
-8
@@ -7,6 +7,7 @@
|
||||
|
||||
package com.facebook.react.bridgeless.internal.bolts;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@@ -14,7 +15,8 @@ import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
/** Collection of {@link Executor}s to use in conjunction with {@link Task}. */
|
||||
/* package */ final class BoltsExecutors {
|
||||
/* package */
|
||||
final class BoltsExecutors {
|
||||
|
||||
private static final BoltsExecutors INSTANCE = new BoltsExecutors();
|
||||
|
||||
@@ -26,9 +28,9 @@ import java.util.concurrent.ScheduledExecutorService;
|
||||
return javaRuntimeName.toLowerCase(Locale.US).contains("android");
|
||||
}
|
||||
|
||||
private final ExecutorService background;
|
||||
private final ScheduledExecutorService scheduled;
|
||||
private final Executor immediate;
|
||||
private final @NonNull ExecutorService background;
|
||||
private final @NonNull ScheduledExecutorService scheduled;
|
||||
private final @NonNull Executor immediate;
|
||||
|
||||
private BoltsExecutors() {
|
||||
background =
|
||||
@@ -40,11 +42,11 @@ import java.util.concurrent.ScheduledExecutorService;
|
||||
}
|
||||
|
||||
/** An {@link java.util.concurrent.Executor} that executes tasks in parallel. */
|
||||
public static ExecutorService background() {
|
||||
public static @NonNull ExecutorService background() {
|
||||
return INSTANCE.background;
|
||||
}
|
||||
|
||||
/* package */ static ScheduledExecutorService scheduled() {
|
||||
/* package */ static @NonNull ScheduledExecutorService scheduled() {
|
||||
return INSTANCE.scheduled;
|
||||
}
|
||||
|
||||
@@ -53,7 +55,7 @@ import java.util.concurrent.ScheduledExecutorService;
|
||||
* stack runs too deep, at which point it will delegate to {@link BoltsExecutors#background} in
|
||||
* order to trim the stack.
|
||||
*/
|
||||
/* package */ static Executor immediate() {
|
||||
/* package */ static @NonNull Executor immediate() {
|
||||
return INSTANCE.immediate;
|
||||
}
|
||||
|
||||
@@ -102,7 +104,7 @@ import java.util.concurrent.ScheduledExecutorService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
public void execute(@NonNull Runnable command) {
|
||||
int depth = incrementDepth();
|
||||
try {
|
||||
if (depth <= MAX_DEPTH) {
|
||||
|
||||
+3
-2
@@ -7,6 +7,7 @@
|
||||
|
||||
package com.facebook.react.bridgeless.internal.bolts;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.CancellationException;
|
||||
|
||||
@@ -29,7 +30,7 @@ public class CancellationToken {
|
||||
|
||||
private final CancellationTokenSource tokenSource;
|
||||
|
||||
/* package */ CancellationToken(CancellationTokenSource tokenSource) {
|
||||
/* package */ CancellationToken(@NonNull CancellationTokenSource tokenSource) {
|
||||
this.tokenSource = tokenSource;
|
||||
}
|
||||
|
||||
@@ -49,7 +50,7 @@ public class CancellationToken {
|
||||
* @return a {@link CancellationTokenRegistration} instance that can be used to unregister the
|
||||
* action.
|
||||
*/
|
||||
public CancellationTokenRegistration register(Runnable action) {
|
||||
public @NonNull CancellationTokenRegistration register(@NonNull Runnable action) {
|
||||
return tokenSource.register(action);
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -7,6 +7,8 @@
|
||||
|
||||
package com.facebook.react.bridgeless.internal.bolts;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import java.io.Closeable;
|
||||
|
||||
/**
|
||||
@@ -17,12 +19,12 @@ import java.io.Closeable;
|
||||
public class CancellationTokenRegistration implements Closeable {
|
||||
|
||||
private final Object lock = new Object();
|
||||
private CancellationTokenSource tokenSource;
|
||||
private Runnable action;
|
||||
private @Nullable CancellationTokenSource tokenSource;
|
||||
private @Nullable Runnable action;
|
||||
private boolean closed;
|
||||
|
||||
/* package */ CancellationTokenRegistration(
|
||||
CancellationTokenSource tokenSource, Runnable action) {
|
||||
@NonNull CancellationTokenSource tokenSource, @NonNull Runnable action) {
|
||||
this.tokenSource = tokenSource;
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
+11
-8
@@ -7,6 +7,8 @@
|
||||
|
||||
package com.facebook.react.bridgeless.internal.bolts;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import java.io.Closeable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -27,9 +29,9 @@ import java.util.concurrent.TimeUnit;
|
||||
public class CancellationTokenSource implements Closeable {
|
||||
|
||||
private final Object lock = new Object();
|
||||
private final List<CancellationTokenRegistration> registrations = new ArrayList<>();
|
||||
private final ScheduledExecutorService executor = BoltsExecutors.scheduled();
|
||||
private ScheduledFuture<?> scheduledCancellation;
|
||||
private final @NonNull List<CancellationTokenRegistration> registrations = new ArrayList<>();
|
||||
private final @NonNull ScheduledExecutorService executor = BoltsExecutors.scheduled();
|
||||
@Nullable private ScheduledFuture<?> scheduledCancellation;
|
||||
private boolean cancellationRequested;
|
||||
private boolean closed;
|
||||
|
||||
@@ -48,7 +50,7 @@ public class CancellationTokenSource implements Closeable {
|
||||
}
|
||||
|
||||
/** @return the token that can be passed to asynchronous method to control cancellation. */
|
||||
public CancellationToken getToken() {
|
||||
public @NonNull CancellationToken getToken() {
|
||||
synchronized (lock) {
|
||||
throwIfClosed();
|
||||
return new CancellationToken(this);
|
||||
@@ -84,7 +86,7 @@ public class CancellationTokenSource implements Closeable {
|
||||
cancelAfter(delay, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
private void cancelAfter(long delay, TimeUnit timeUnit) {
|
||||
private void cancelAfter(long delay, @NonNull TimeUnit timeUnit) {
|
||||
if (delay < -1) {
|
||||
throw new IllegalArgumentException("Delay must be >= -1");
|
||||
}
|
||||
@@ -137,7 +139,8 @@ public class CancellationTokenSource implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ CancellationTokenRegistration register(Runnable action) {
|
||||
/* package */ @NonNull
|
||||
CancellationTokenRegistration register(@NonNull Runnable action) {
|
||||
CancellationTokenRegistration ctr;
|
||||
synchronized (lock) {
|
||||
throwIfClosed();
|
||||
@@ -165,7 +168,7 @@ public class CancellationTokenSource implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ void unregister(CancellationTokenRegistration registration) {
|
||||
/* package */ void unregister(@NonNull CancellationTokenRegistration registration) {
|
||||
synchronized (lock) {
|
||||
throwIfClosed();
|
||||
registrations.remove(registration);
|
||||
@@ -178,7 +181,7 @@ public class CancellationTokenSource implements Closeable {
|
||||
// to be synchronized with state changes you should provide external synchronization.
|
||||
// If this is invoked without external synchronization there is a probability the token becomes
|
||||
// cancelled concurrently.
|
||||
private void notifyListeners(List<CancellationTokenRegistration> registrations) {
|
||||
private void notifyListeners(@NonNull List<CancellationTokenRegistration> registrations) {
|
||||
for (CancellationTokenRegistration registration : registrations) {
|
||||
registration.runAction();
|
||||
}
|
||||
|
||||
+6
-4
@@ -7,25 +7,27 @@
|
||||
|
||||
package com.facebook.react.bridgeless.internal.bolts;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Provides a class that can be used for capturing variables in an anonymous class implementation.
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public class Capture<T> {
|
||||
private T value;
|
||||
private @Nullable T value;
|
||||
|
||||
public Capture() {}
|
||||
|
||||
public Capture(T value) {
|
||||
public Capture(@Nullable T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public T get() {
|
||||
public @Nullable T get() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void set(T value) {
|
||||
public void set(@Nullable T value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -7,6 +7,9 @@
|
||||
|
||||
package com.facebook.react.bridgeless.internal.bolts;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A function to be called after a task completes.
|
||||
*
|
||||
@@ -16,5 +19,6 @@ package com.facebook.react.bridgeless.internal.bolts;
|
||||
* @see Task
|
||||
*/
|
||||
public interface Continuation<TTaskResult, TContinuationResult> {
|
||||
TContinuationResult then(Task<TTaskResult> task) throws Exception;
|
||||
@Nullable
|
||||
TContinuationResult then(@NonNull Task<TTaskResult> task) throws Exception;
|
||||
}
|
||||
|
||||
+3
-1
@@ -7,13 +7,15 @@
|
||||
|
||||
package com.facebook.react.bridgeless.internal.bolts;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This is a wrapper class for emphasizing that task failed due to bad {@code Executor}, rather than
|
||||
* the continuation block it self.
|
||||
*/
|
||||
public class ExecutorException extends RuntimeException {
|
||||
|
||||
public ExecutorException(Exception e) {
|
||||
public ExecutorException(@Nullable Exception e) {
|
||||
super("An exception was thrown by an Executor", e);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-6
@@ -7,6 +7,9 @@
|
||||
|
||||
package com.facebook.react.bridgeless.internal.bolts;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Allows safe orchestration of a task's completion, preventing the consumer from prematurely
|
||||
* completing the task. Essentially, it represents the producer side of a Task<TResult>, providing
|
||||
@@ -15,7 +18,7 @@ package com.facebook.react.bridgeless.internal.bolts;
|
||||
*/
|
||||
public class TaskCompletionSource<TResult> {
|
||||
|
||||
private final Task<TResult> task;
|
||||
@NonNull private final Task<TResult> task;
|
||||
|
||||
/**
|
||||
* Creates a TaskCompletionSource that orchestrates a Task. This allows the creator of a task to
|
||||
@@ -26,7 +29,7 @@ public class TaskCompletionSource<TResult> {
|
||||
}
|
||||
|
||||
/** @return the Task associated with this TaskCompletionSource. */
|
||||
public Task<TResult> getTask() {
|
||||
public @NonNull Task<TResult> getTask() {
|
||||
return task;
|
||||
}
|
||||
|
||||
@@ -36,12 +39,12 @@ public class TaskCompletionSource<TResult> {
|
||||
}
|
||||
|
||||
/** Sets the result on the Task if the Task hasn't already been completed. */
|
||||
public boolean trySetResult(TResult result) {
|
||||
public boolean trySetResult(@Nullable TResult result) {
|
||||
return task.trySetResult(result);
|
||||
}
|
||||
|
||||
/** Sets the error on the Task if the Task hasn't already been completed. */
|
||||
public boolean trySetError(Exception error) {
|
||||
public boolean trySetError(@Nullable Exception error) {
|
||||
return task.trySetError(error);
|
||||
}
|
||||
|
||||
@@ -53,14 +56,14 @@ public class TaskCompletionSource<TResult> {
|
||||
}
|
||||
|
||||
/** Sets the result of the Task, throwing if the Task has already been completed. */
|
||||
public void setResult(TResult result) {
|
||||
public void setResult(@Nullable TResult result) {
|
||||
if (!trySetResult(result)) {
|
||||
throw new IllegalStateException("Cannot set the result of a completed task.");
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets the error of the Task, throwing if the Task has already been completed. */
|
||||
public void setError(Exception error) {
|
||||
public void setError(@Nullable Exception error) {
|
||||
if (!trySetError(error)) {
|
||||
throw new IllegalStateException("Cannot set the error on a completed task.");
|
||||
}
|
||||
|
||||
+4
-2
@@ -7,15 +7,17 @@
|
||||
|
||||
package com.facebook.react.bridgeless.internal.bolts;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This class is used to retain a faulted task until either its error is observed or it is
|
||||
* finalized. If it is finalized with a task, then the uncaught exception handler is exected with an
|
||||
* UnobservedTaskException.
|
||||
*/
|
||||
class UnobservedErrorNotifier {
|
||||
private Task<?> task;
|
||||
@Nullable private Task<?> task;
|
||||
|
||||
public UnobservedErrorNotifier(Task<?> task) {
|
||||
public UnobservedErrorNotifier(@Nullable Task<?> task) {
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -7,9 +7,11 @@
|
||||
|
||||
package com.facebook.react.bridgeless.internal.bolts;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/** Used to signify that a Task's error went unobserved. */
|
||||
public class UnobservedTaskException extends RuntimeException {
|
||||
public UnobservedTaskException(Throwable cause) {
|
||||
public UnobservedTaskException(@Nullable Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user