Format Java code in xplat/js/react-native-github

Summary:
This diff formats the Java class files inside xplat/js/react-native-github. Since google-java-format was enabled in D16071401 we want to codemode the existing code so that users don't have to deal with formatter lint noise at diff-time.

```arc f --paths-cmd 'hg files -I "**/*.java"'```

drop-conflicts

Reviewed By: cpojer

Differential Revision: D16071725

fbshipit-source-id: fc6e3852e45742c109f0c5ac4065d64201c74204
This commit is contained in:
Oleksandr Melnykov
2019-07-02 04:16:46 -07:00
committed by Facebook Github Bot
parent 61e95e5cbf
commit 6c0f73b322
681 changed files with 14082 additions and 16365 deletions
@@ -11,6 +11,8 @@ import com.facebook.debug.debugoverlay.model.DebugOverlayTag;
public interface Printer {
void logMessage(final DebugOverlayTag tag, final String message, Object... args);
void logMessage(final DebugOverlayTag tag, final String message);
boolean shouldDisplayLogMessage(final DebugOverlayTag tag);
}
@@ -28,15 +28,9 @@ public class ReactDebugOverlayTags {
"UI Manager View Operations (requires restart\nwarning: this is spammy)",
Color.CYAN);
public static final DebugOverlayTag FABRIC_UI_MANAGER =
new DebugOverlayTag(
"FabricUIManager",
"Fabric UI Manager View Operations",
Color.CYAN);
new DebugOverlayTag("FabricUIManager", "Fabric UI Manager View Operations", Color.CYAN);
public static final DebugOverlayTag FABRIC_RECONCILER =
new DebugOverlayTag(
"FabricReconciler",
"Reconciler for Fabric",
Color.CYAN);
new DebugOverlayTag("FabricReconciler", "Reconciler for Fabric", Color.CYAN);
public static final DebugOverlayTag RELAY =
new DebugOverlayTag("Relay", "including prefetching", Color.rgb(0xFF, 0x99, 0x00));
}
@@ -11,11 +11,11 @@ import com.facebook.soloader.SoLoader;
/**
* A Java Object that has native memory allocated corresponding to this instance.
*
* NB: THREAD SAFETY (this comment also exists at Countable.cpp)
* <p>NB: THREAD SAFETY (this comment also exists at Countable.cpp)
*
* {@link #dispose} deletes the corresponding native object on whatever thread the method is called
* on. In the common case when this is called by Countable#finalize(), this will be called on the
* system finalizer thread. If you manually call dispose on the Java object, the native object
* <p>{@link #dispose} deletes the corresponding native object on whatever thread the method is
* called on. In the common case when this is called by Countable#finalize(), this will be called on
* the system finalizer thread. If you manually call dispose on the Java object, the native object
* will be deleted synchronously on that thread.
*/
@DoNotStrip
@@ -26,8 +26,7 @@ public class Countable {
}
// Private C++ instance
@DoNotStrip
private long mInstance = 0;
@DoNotStrip private long mInstance = 0;
public native void dispose();
@@ -8,9 +8,7 @@ package com.facebook.jni;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.soloader.SoLoader;
/**
* Utility class to determine CPU capabilities
*/
/** Utility class to determine CPU capabilities */
@DoNotStrip
public class CpuCapabilitiesJni {
@@ -26,5 +24,4 @@ public class CpuCapabilitiesJni {
@DoNotStrip
public static native boolean nativeDeviceSupportsX86();
}
@@ -12,12 +12,12 @@ import java.util.concurrent.atomic.AtomicReference;
/**
* A thread which invokes the "destruct" routine for objects after they have been garbage collected.
*
* An object which needs to be destructed should create a static subclass of {@link Destructor}.
* Once the referent object is garbage collected, the DestructorThread will callback to the
* {@link Destructor#destruct()} method.
* <p>An object which needs to be destructed should create a static subclass of {@link Destructor}.
* Once the referent object is garbage collected, the DestructorThread will callback to the {@link
* Destructor#destruct()} method.
*
* The underlying thread in DestructorThread starts when the first Destructor is constructed
* and then runs indefinitely.
* <p>The underlying thread in DestructorThread starts when the first Destructor is constructed and
* then runs indefinitely.
*/
public class DestructorThread {
@@ -48,6 +48,7 @@ public class DestructorThread {
private static DestructorList sDestructorList;
/** A thread safe stack where new Destructors are placed before being add to sDestructorList. */
private static DestructorStack sDestructorStack;
private static ReferenceQueue sReferenceQueue;
private static Thread sThread;
@@ -55,27 +56,28 @@ public class DestructorThread {
sDestructorStack = new DestructorStack();
sReferenceQueue = new ReferenceQueue();
sDestructorList = new DestructorList();
sThread = new Thread("HybridData DestructorThread") {
@Override
public void run() {
while (true) {
try {
Destructor current = (Destructor) sReferenceQueue.remove();
current.destruct();
sThread =
new Thread("HybridData DestructorThread") {
@Override
public void run() {
while (true) {
try {
Destructor current = (Destructor) sReferenceQueue.remove();
current.destruct();
// If current is in the sDestructorStack,
// transfer all the Destructors in the stack to the list.
if (current.previous == null) {
sDestructorStack.transferAllToList();
// If current is in the sDestructorStack,
// transfer all the Destructors in the stack to the list.
if (current.previous == null) {
sDestructorStack.transferAllToList();
}
DestructorList.drop(current);
} catch (InterruptedException e) {
// Continue. This thread should never be terminated.
}
}
DestructorList.drop(current);
} catch (InterruptedException e) {
// Continue. This thread should never be terminated.
}
}
}
};
};
sThread.start();
}
@@ -4,8 +4,8 @@
// LICENSE file in the root directory of this source tree.
package com.facebook.jni;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public abstract class HybridClassBase extends HybridData {
}
public abstract class HybridClassBase extends HybridData {}
@@ -5,19 +5,16 @@
package com.facebook.jni;
import android.util.Log;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.soloader.SoLoader;
/**
* This object holds a native C++ member for hybrid Java/C++ objects.
*
* NB: THREAD SAFETY
* <p>NB: THREAD SAFETY
*
* {@link #resetNative} deletes the corresponding native object synchronously on whatever thread
* the method is called on. Otherwise, deletion will occur on the {@link DestructorThread}
* thread.
* <p>{@link #resetNative} deletes the corresponding native object synchronously on whatever thread
* the method is called on. Otherwise, deletion will occur on the {@link DestructorThread} thread.
*/
@DoNotStrip
public class HybridData {
@@ -26,26 +23,24 @@ public class HybridData {
SoLoader.loadLibrary("fb");
}
@DoNotStrip
private Destructor mDestructor = new Destructor(this);
@DoNotStrip private Destructor mDestructor = new Destructor(this);
/**
* To explicitly delete the instance, call resetNative(). If the C++
* instance is referenced after this is called, a NullPointerException will
* be thrown. resetNative() may be called multiple times safely. Because
* the {@link DestructorThread} also calls resetNative, the instance will not leak if this is
* not called, but timing of deletion and the thread the C++ dtor is called
* on will be at the whim of the Java GC. If you want to control the thread
* and timing of the destructor, you should call resetNative() explicitly.
* To explicitly delete the instance, call resetNative(). If the C++ instance is referenced after
* this is called, a NullPointerException will be thrown. resetNative() may be called multiple
* times safely. Because the {@link DestructorThread} also calls resetNative, the instance will
* not leak if this is not called, but timing of deletion and the thread the C++ dtor is called on
* will be at the whim of the Java GC. If you want to control the thread and timing of the
* destructor, you should call resetNative() explicitly.
*/
public synchronized void resetNative() {
mDestructor.destruct();
}
/**
* N.B. Thread safety.
* If you call isValid from a different thread than {@link #resetNative()} then be sure to
* do so while synchronizing on the hybrid. For example:
* N.B. Thread safety. If you call isValid from a different thread than {@link #resetNative()}
* then be sure to do so while synchronizing on the hybrid. For example:
*
* <pre><code>
* synchronized(hybrid) {
* if (hybrid.isValid) {
@@ -61,8 +56,7 @@ public class HybridData {
public static class Destructor extends DestructorThread.Destructor {
// Private C++ instance
@DoNotStrip
private long mNativePointer;
@DoNotStrip private long mNativePointer;
Destructor(Object referent) {
super(referent);
@@ -1,31 +1,26 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.jni;
import com.facebook.proguard.annotations.DoNotStrip;
import java.util.Iterator;
import javax.annotation.Nullable;
import java.util.Iterator;
/**
* To iterate over an Iterator from C++ requires two calls per entry: hasNext()
* and next(). This helper reduces it to one call and one field get per entry.
* It does not use a generic argument, since in C++, the types will be erased,
* anyway. This is *not* a {@link java.util.Iterator}.
* To iterate over an Iterator from C++ requires two calls per entry: hasNext() and next(). This
* helper reduces it to one call and one field get per entry. It does not use a generic argument,
* since in C++, the types will be erased, anyway. This is *not* a {@link java.util.Iterator}.
*/
@DoNotStrip
public class IteratorHelper {
private final Iterator mIterator;
// This is private, but accessed via JNI.
@DoNotStrip
private @Nullable Object mElement;
@DoNotStrip private @Nullable Object mElement;
@DoNotStrip
public IteratorHelper(Iterator iterator) {
@@ -38,8 +33,8 @@ public class IteratorHelper {
}
/**
* Moves the helper to the next entry in the map, if any. Returns true iff
* there is an entry to read.
* Moves the helper to the next entry in the map, if any. Returns true iff there is an entry to
* read.
*/
@DoNotStrip
boolean hasNext() {
@@ -1,24 +1,21 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.jni;
import javax.annotation.Nullable;
import com.facebook.proguard.annotations.DoNotStrip;
import java.util.Iterator;
import java.util.Map;
import com.facebook.proguard.annotations.DoNotStrip;
import javax.annotation.Nullable;
/**
* To iterate over a Map from C++ requires four calls per entry: hasNext(),
* next(), getKey(), getValue(). This helper reduces it to one call and two
* field gets per entry. It does not use a generic argument, since in C++, the
* types will be erased, anyway. This is *not* a {@link java.util.Iterator}.
* To iterate over a Map from C++ requires four calls per entry: hasNext(), next(), getKey(),
* getValue(). This helper reduces it to one call and two field gets per entry. It does not use a
* generic argument, since in C++, the types will be erased, anyway. This is *not* a {@link
* java.util.Iterator}.
*/
@DoNotStrip
public class MapIteratorHelper {
@@ -32,8 +29,8 @@ public class MapIteratorHelper {
}
/**
* Moves the helper to the next entry in the map, if any. Returns true iff
* there is an entry to read.
* Moves the helper to the next entry in the map, if any. Returns true iff there is an entry to
* read.
*/
@DoNotStrip
boolean hasNext() {
@@ -1,18 +1,14 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.jni;
import com.facebook.jni.HybridData;
import com.facebook.proguard.annotations.DoNotStrip;
/**
* A Runnable that has a native run implementation.
*/
/** A Runnable that has a native run implementation. */
@DoNotStrip
public class NativeRunnable implements Runnable {
@@ -1,19 +1,15 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.perftest;
/**
* PerfTestConfig stub.
*/
/** PerfTestConfig stub. */
public class PerfTestConfig {
public boolean isRunningInPerfTest() {
return false;
}
}
@@ -1,24 +1,22 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.proguard.annotations;
import static java.lang.annotation.RetentionPolicy.CLASS;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.RetentionPolicy.CLASS;
/**
* Add this annotation to a class, method, or field to instruct Proguard to not strip it out.
*
* This is useful for methods called via reflection that could appear as unused to Proguard.
* <p>This is useful for methods called via reflection that could appear as unused to Proguard.
*/
@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR })
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(CLASS)
public @interface DoNotStrip {
}
public @interface DoNotStrip {}
@@ -1,28 +1,26 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.proguard.annotations;
import static java.lang.annotation.RetentionPolicy.CLASS;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.RetentionPolicy.CLASS;
/**
* Add this annotation to a class, to keep all "void set*(***)" and get* methods.
*
* <p>This is useful for classes that are controlled by animator-like classes that control
* various properties with reflection.
* <p>This is useful for classes that are controlled by animator-like classes that control various
* properties with reflection.
*
* <p><b>NOTE:</b> This is <em>not</em> needed for Views because their getters and setters
* are automatically kept by the default Android SDK ProGuard config.
* <p><b>NOTE:</b> This is <em>not</em> needed for Views because their getters and setters are
* automatically kept by the default Android SDK ProGuard config.
*/
@Target({ElementType.TYPE})
@Retention(CLASS)
public @interface KeepGettersAndSetters {
}
public @interface KeepGettersAndSetters {}
@@ -20,7 +20,6 @@ import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import com.facebook.react.TurboReactPackage;
/**
* {@code CompositeReactPackage} allows to create a single package composed of views and modules
@@ -50,14 +49,14 @@ public class CompositeReactPackage implements ViewManagerOnDemandReactPackage, R
final Map<String, NativeModule> moduleMap = new HashMap<>();
for (ReactPackage reactPackage : mChildReactPackages) {
/**
* For now, we eagerly initialize the NativeModules inside TurboReactPackages.
* Ultimately, we should turn CompositeReactPackage into a TurboReactPackage
* and remove this eager initialization.
* For now, we eagerly initialize the NativeModules inside TurboReactPackages. Ultimately, we
* should turn CompositeReactPackage into a TurboReactPackage and remove this eager
* initialization.
*
* TODO: T45627020
* <p>TODO: T45627020
*/
if (reactPackage instanceof TurboReactPackage) {
TurboReactPackage turboReactPackage = (TurboReactPackage)reactPackage;
TurboReactPackage turboReactPackage = (TurboReactPackage) reactPackage;
ReactModuleInfoProvider moduleInfoProvider = turboReactPackage.getReactModuleInfoProvider();
Map<String, ReactModuleInfo> moduleInfos = moduleInfoProvider.getReactModuleInfos();
@@ -6,6 +6,7 @@
*/
package com.facebook.react;
import static com.facebook.react.bridge.ReactMarkerConstants.*;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_END;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_START;
import static com.facebook.react.bridge.ReactMarkerConstants.PROCESS_CORE_REACT_PACKAGE_END;
@@ -18,11 +19,11 @@ import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.module.annotations.ReactModuleList;
import com.facebook.react.module.model.ReactModuleInfo;
import com.facebook.react.module.model.ReactModuleInfoProvider;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.modules.core.ExceptionsManagerModule;
import com.facebook.react.modules.core.Timing;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.modules.core.HeadlessJsTaskSupportModule;
import com.facebook.react.modules.core.Timing;
import com.facebook.react.modules.debug.DevSettingsModule;
import com.facebook.react.modules.debug.SourceCodeModule;
import com.facebook.react.modules.deviceinfo.DeviceInfoModule;
@@ -31,14 +32,10 @@ import com.facebook.react.uimanager.UIImplementationProvider;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.ViewManager;
import com.facebook.systrace.Systrace;
import java.util.Collections;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.facebook.react.bridge.ReactMarkerConstants.*;
import javax.annotation.Nullable;
/**
* This is the basic module to support React Native. The debug modules are now in DebugCorePackage.
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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;
import com.facebook.react.bridge.ModuleSpec;
@@ -24,15 +23,13 @@ import javax.inject.Provider;
* view managers from).
*/
@ReactModuleList(
nativeModules = {
JSCHeapCapture.class,
JSDevSupport.class,
}
)
nativeModules = {
JSCHeapCapture.class,
JSDevSupport.class,
})
/* package */ class DebugCorePackage extends LazyReactPackage {
DebugCorePackage() {
}
DebugCorePackage() {}
@Override
public List<ModuleSpec> getNativeModules(final ReactApplicationContext reactContext) {
@@ -5,13 +5,10 @@
package com.facebook.react;
import com.facebook.react.bridge.NativeModule;
import javax.inject.Provider;
import com.facebook.react.bridge.NativeModule;
/**
* Provider for an already initialized and non-lazy NativeModule.
*/
/** Provider for an already initialized and non-lazy NativeModule. */
public class EagerModuleProvider implements Provider<NativeModule> {
private final NativeModule mModule;
@@ -1,17 +1,11 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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;
import javax.annotation.Nullable;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import android.annotation.SuppressLint;
import android.app.Service;
import android.content.BroadcastReceiver;
@@ -19,23 +13,25 @@ import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.PowerManager;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.jstasks.HeadlessJsTaskEventListener;
import com.facebook.react.jstasks.HeadlessJsTaskConfig;
import com.facebook.react.jstasks.HeadlessJsTaskContext;
import com.facebook.react.jstasks.HeadlessJsTaskEventListener;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.annotation.Nullable;
/**
* Base class for running JS without a UI. Generally, you only need to override
* {@link #getTaskConfig}, which is called for every {@link #onStartCommand}. The
* result, if not {@code null}, is used to run a JS task.
* Base class for running JS without a UI. Generally, you only need to override {@link
* #getTaskConfig}, which is called for every {@link #onStartCommand}. The result, if not {@code
* null}, is used to run a JS task.
*
* If you need more fine-grained control over how tasks are run, you can override
* {@link #onStartCommand} and call {@link #startTask} depending on your custom logic.
* <p>If you need more fine-grained control over how tasks are run, you can override {@link
* #onStartCommand} and call {@link #startTask} depending on your custom logic.
*
* If you're starting a {@code HeadlessJsTaskService} from a {@code BroadcastReceiver} (e.g.
* <p>If you're starting a {@code HeadlessJsTaskService} from a {@code BroadcastReceiver} (e.g.
* handling push notifications), make sure to call {@link #acquireWakeLockNow} before returning from
* {@link BroadcastReceiver#onReceive}, to make sure the device doesn't go to sleep before the
* service is started.
@@ -57,9 +53,10 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
/**
* Called from {@link #onStartCommand} to create a {@link HeadlessJsTaskConfig} for this intent.
*
* @param intent the {@link Intent} received in {@link #onStartCommand}.
* @return a {@link HeadlessJsTaskConfig} to be used with {@link #startTask}, or
* {@code null} to ignore this command.
* @return a {@link HeadlessJsTaskConfig} to be used with {@link #startTask}, or {@code null} to
* ignore this command.
*/
protected @Nullable HeadlessJsTaskConfig getTaskConfig(Intent intent) {
return null;
@@ -72,10 +69,10 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
public static void acquireWakeLockNow(Context context) {
if (sWakeLock == null || !sWakeLock.isHeld()) {
PowerManager powerManager =
Assertions.assertNotNull((PowerManager) context.getSystemService(POWER_SERVICE));
sWakeLock = powerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK,
HeadlessJsTaskService.class.getCanonicalName());
Assertions.assertNotNull((PowerManager) context.getSystemService(POWER_SERVICE));
sWakeLock =
powerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, HeadlessJsTaskService.class.getCanonicalName());
sWakeLock.setReferenceCounted(false);
sWakeLock.acquire();
}
@@ -89,7 +86,7 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
/**
* Start a task. This method handles starting a new React instance if required.
*
* Has to be called on the UI thread.
* <p>Has to be called on the UI thread.
*
* @param taskConfig describes what task to start and the parameters to pass to it
*/
@@ -97,17 +94,17 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
UiThreadUtil.assertOnUiThread();
acquireWakeLockNow(this);
final ReactInstanceManager reactInstanceManager =
getReactNativeHost().getReactInstanceManager();
getReactNativeHost().getReactInstanceManager();
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
if (reactContext == null) {
reactInstanceManager
.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
@Override
public void onReactContextInitialized(ReactContext reactContext) {
invokeStartTask(reactContext, taskConfig);
reactInstanceManager.removeReactInstanceEventListener(this);
}
});
reactInstanceManager.addReactInstanceEventListener(
new ReactInstanceManager.ReactInstanceEventListener() {
@Override
public void onReactContextInitialized(ReactContext reactContext) {
invokeStartTask(reactContext, taskConfig);
reactInstanceManager.removeReactInstanceEventListener(this);
}
});
reactInstanceManager.createReactContextInBackground();
} else {
invokeStartTask(reactContext, taskConfig);
@@ -115,18 +112,18 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
}
private void invokeStartTask(ReactContext reactContext, final HeadlessJsTaskConfig taskConfig) {
final HeadlessJsTaskContext headlessJsTaskContext = HeadlessJsTaskContext.getInstance(reactContext);
final HeadlessJsTaskContext headlessJsTaskContext =
HeadlessJsTaskContext.getInstance(reactContext);
headlessJsTaskContext.addTaskEventListener(this);
UiThreadUtil.runOnUiThread(
new Runnable() {
@Override
public void run() {
int taskId = headlessJsTaskContext.startTask(taskConfig);
mActiveTasks.add(taskId);
}
}
);
new Runnable() {
@Override
public void run() {
int taskId = headlessJsTaskContext.startTask(taskConfig);
mActiveTasks.add(taskId);
}
});
}
@Override
@@ -138,7 +135,7 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
if (reactContext != null) {
HeadlessJsTaskContext headlessJsTaskContext =
HeadlessJsTaskContext.getInstance(reactContext);
HeadlessJsTaskContext.getInstance(reactContext);
headlessJsTaskContext.removeTaskEventListener(this);
}
}
@@ -148,7 +145,7 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
}
@Override
public void onHeadlessJsTaskStart(int taskId) { }
public void onHeadlessJsTaskStart(int taskId) {}
@Override
public void onHeadlessJsTaskFinish(int taskId) {
@@ -160,10 +157,10 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
/**
* Get the {@link ReactNativeHost} used by this app. By default, assumes {@link #getApplication()}
* is an instance of {@link ReactApplication} and calls
* {@link ReactApplication#getReactNativeHost()}. Override this method if your application class
* does not implement {@code ReactApplication} or you simply have a different mechanism for
* storing a {@code ReactNativeHost}, e.g. as a static field somewhere.
* is an instance of {@link ReactApplication} and calls {@link
* ReactApplication#getReactNativeHost()}. Override this method if your application class does not
* implement {@code ReactApplication} or you simply have a different mechanism for storing a
* {@code ReactNativeHost}, e.g. as a static field somewhere.
*/
protected ReactNativeHost getReactNativeHost() {
return ((ReactApplication) getApplication()).getReactNativeHost();
@@ -76,7 +76,8 @@ public abstract class LazyReactPackage implements ReactPackage {
* @param reactContext
* @return
*/
public Iterable<ModuleHolder> getNativeModuleIterator(final ReactApplicationContext reactContext) {
public Iterable<ModuleHolder> getNativeModuleIterator(
final ReactApplicationContext reactContext) {
final Map<String, ReactModuleInfo> reactModuleInfoMap =
getReactModuleInfoProvider().getReactModuleInfos();
final List<ModuleSpec> nativeModules = getNativeModules(reactContext);
@@ -13,12 +13,10 @@ import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* Translates and routes memory pressure events to the current catalyst instance.
*/
/** Translates and routes memory pressure events to the current catalyst instance. */
public class MemoryPressureRouter implements ComponentCallbacks2 {
private final Set<MemoryPressureListener> mListeners =
Collections.synchronizedSet(new LinkedHashSet<MemoryPressureListener>());
Collections.synchronizedSet(new LinkedHashSet<MemoryPressureListener>());
MemoryPressureRouter(Context context) {
context.getApplicationContext().registerComponentCallbacks(this);
@@ -28,16 +26,12 @@ public class MemoryPressureRouter implements ComponentCallbacks2 {
context.getApplicationContext().unregisterComponentCallbacks(this);
}
/**
* Add a listener to be notified of memory pressure events.
*/
/** Add a listener to be notified of memory pressure events. */
public void addMemoryPressureListener(MemoryPressureListener listener) {
mListeners.add(listener);
}
/**
* Remove a listener previously added with {@link #addMemoryPressureListener}.
*/
/** Remove a listener previously added with {@link #addMemoryPressureListener}. */
public void removeMemoryPressureListener(MemoryPressureListener listener) {
mListeners.remove(listener);
}
@@ -48,18 +42,16 @@ public class MemoryPressureRouter implements ComponentCallbacks2 {
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
}
public void onConfigurationChanged(Configuration newConfig) {}
@Override
public void onLowMemory() {
}
public void onLowMemory() {}
private void dispatchMemoryPressure(int level) {
// copy listeners array to avoid ConcurrentModificationException if any of the listeners remove
// themselves in handleMemoryPressure()
MemoryPressureListener[] listeners =
mListeners.toArray(new MemoryPressureListener[mListeners.size()]);
mListeners.toArray(new MemoryPressureListener[mListeners.size()]);
for (MemoryPressureListener listener : listeners) {
listener.handleMemoryPressure(level);
}
@@ -64,7 +64,8 @@ public class NativeModuleRegistryBuilder {
// already in the list, and then NOT add the new module, since that will be directly exposed
// Note that is someone uses {@link NativeModuleRegistry#registerModules}, we will NOT check
// for TurboModules - assuming that people wanted to explicitly register native modules there
// for TurboModules - assuming that people wanted to explicitly register native modules
// there
continue;
}
mModules.put(name, moduleHolder);
@@ -1,26 +1,21 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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;
import javax.annotation.Nullable;
import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.KeyEvent;
import androidx.appcompat.app.AppCompatActivity;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.modules.core.PermissionAwareActivity;
import com.facebook.react.modules.core.PermissionListener;
import javax.annotation.Nullable;
/**
* Base Activity for React Native applications.
*/
/** Base Activity for React Native applications. */
public abstract class ReactActivity extends AppCompatActivity
implements DefaultHardwareBackBtnHandler, PermissionAwareActivity {
@@ -31,17 +26,14 @@ public abstract class ReactActivity extends AppCompatActivity
}
/**
* Returns the name of the main component registered from JavaScript.
* This is used to schedule rendering of the component.
* e.g. "MoviesApp"
* Returns the name of the main component registered from JavaScript. This is used to schedule
* rendering of the component. e.g. "MoviesApp"
*/
protected @Nullable String getMainComponentName() {
return null;
}
/**
* Called at construction time, override if you have a custom delegate implementation.
*/
/** Called at construction time, override if you have a custom delegate implementation. */
protected ReactActivityDelegate createReactActivityDelegate() {
return new ReactActivityDelegate(this, getMainComponentName());
}
@@ -111,17 +103,13 @@ public abstract class ReactActivity extends AppCompatActivity
@Override
public void requestPermissions(
String[] permissions,
int requestCode,
PermissionListener listener) {
String[] permissions, int requestCode, PermissionListener listener) {
mDelegate.requestPermissions(permissions, requestCode, listener);
}
@Override
public void onRequestPermissionsResult(
int requestCode,
String[] permissions,
int[] grantResults) {
int requestCode, String[] permissions, int[] grantResults) {
mDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@@ -12,12 +12,9 @@ import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.KeyEvent;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.Callback;
import com.facebook.react.uimanager.RootView;
import com.facebook.react.modules.core.PermissionListener;
import javax.annotation.Nullable;
/**
@@ -54,11 +51,11 @@ public class ReactActivityDelegate {
}
/**
* Get the {@link ReactNativeHost} used by this app. By default, assumes
* {@link Activity#getApplication()} is an instance of {@link ReactApplication} and calls
* {@link ReactApplication#getReactNativeHost()}. Override this method if your application class
* does not implement {@code ReactApplication} or you simply have a different mechanism for
* storing a {@code ReactNativeHost}, e.g. as a static field somewhere.
* Get the {@link ReactNativeHost} used by this app. By default, assumes {@link
* Activity#getApplication()} is an instance of {@link ReactApplication} and calls {@link
* ReactApplication#getReactNativeHost()}. Override this method if your application class does not
* implement {@code ReactApplication} or you simply have a different mechanism for storing a
* {@code ReactNativeHost}, e.g. as a static field somewhere.
*/
protected ReactNativeHost getReactNativeHost() {
return ((ReactApplication) getPlainActivity().getApplication()).getReactNativeHost();
@@ -74,7 +71,9 @@ public class ReactActivityDelegate {
protected void onCreate(Bundle savedInstanceState) {
String mainComponentName = getMainComponentName();
mReactDelegate = new ReactDelegate(getPlainActivity(), getReactNativeHost(), mainComponentName, getLaunchOptions());
mReactDelegate =
new ReactDelegate(
getPlainActivity(), getReactNativeHost(), mainComponentName, getLaunchOptions());
if (mMainComponentName != null) {
loadApp(mainComponentName);
}
@@ -108,8 +107,8 @@ public class ReactActivityDelegate {
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (getReactNativeHost().hasInstance()
&& getReactNativeHost().getUseDeveloperSupport()
&& keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
&& getReactNativeHost().getUseDeveloperSupport()
&& keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
event.startTracking();
return true;
}
@@ -150,25 +149,24 @@ public class ReactActivityDelegate {
@TargetApi(Build.VERSION_CODES.M)
public void requestPermissions(
String[] permissions,
int requestCode,
PermissionListener listener) {
String[] permissions, int requestCode, PermissionListener listener) {
mPermissionListener = listener;
getPlainActivity().requestPermissions(permissions, requestCode);
}
public void onRequestPermissionsResult(
final int requestCode,
final String[] permissions,
final int[] grantResults) {
mPermissionsCallback = new Callback() {
@Override
public void invoke(Object... args) {
if (mPermissionListener != null && mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
mPermissionListener = null;
}
}
};
final int requestCode, final String[] permissions, final int[] grantResults) {
mPermissionsCallback =
new Callback() {
@Override
public void invoke(Object... args) {
if (mPermissionListener != null
&& mPermissionListener.onRequestPermissionsResult(
requestCode, permissions, grantResults)) {
mPermissionListener = null;
}
}
};
}
protected Context getContext() {
@@ -1,47 +1,42 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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;
import android.view.KeyEvent;
import android.view.View;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.common.MapBuilder;
import java.util.Map;
/**
* Responsible for dispatching events specific for hardware inputs.
*/
/** Responsible for dispatching events specific for hardware inputs. */
public class ReactAndroidHWInputDeviceHelper {
/**
* Contains a mapping between handled KeyEvents and the corresponding navigation event
* that should be fired when the KeyEvent is received.
* Contains a mapping between handled KeyEvents and the corresponding navigation event that should
* be fired when the KeyEvent is received.
*/
private static final Map<Integer, String> KEY_EVENTS_ACTIONS = MapBuilder.<Integer, String>builder()
.put(KeyEvent.KEYCODE_DPAD_CENTER, "select")
.put(KeyEvent.KEYCODE_ENTER, "select")
.put(KeyEvent.KEYCODE_SPACE, "select")
.put(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, "playPause")
.put(KeyEvent.KEYCODE_MEDIA_REWIND, "rewind")
.put(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, "fastForward")
.put(KeyEvent.KEYCODE_DPAD_UP, "up")
.put(KeyEvent.KEYCODE_DPAD_RIGHT, "right")
.put(KeyEvent.KEYCODE_DPAD_DOWN, "down")
.put(KeyEvent.KEYCODE_DPAD_LEFT, "left")
.build();
private static final Map<Integer, String> KEY_EVENTS_ACTIONS =
MapBuilder.<Integer, String>builder()
.put(KeyEvent.KEYCODE_DPAD_CENTER, "select")
.put(KeyEvent.KEYCODE_ENTER, "select")
.put(KeyEvent.KEYCODE_SPACE, "select")
.put(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, "playPause")
.put(KeyEvent.KEYCODE_MEDIA_REWIND, "rewind")
.put(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, "fastForward")
.put(KeyEvent.KEYCODE_DPAD_UP, "up")
.put(KeyEvent.KEYCODE_DPAD_RIGHT, "right")
.put(KeyEvent.KEYCODE_DPAD_DOWN, "down")
.put(KeyEvent.KEYCODE_DPAD_LEFT, "left")
.build();
/**
* We keep a reference to the last focused view id
* so that we can send it as a target for key events
* and be able to send a blur event when focus changes.
* We keep a reference to the last focused view id so that we can send it as a target for key
* events and be able to send a blur event when focus changes.
*/
private int mLastFocusedViewId = View.NO_ID;
@@ -51,21 +46,17 @@ public class ReactAndroidHWInputDeviceHelper {
this.mReactRootView = mReactRootView;
}
/**
* Called from {@link ReactRootView}.
* This is the main place the key events are handled.
*/
/** Called from {@link ReactRootView}. This is the main place the key events are handled. */
public void handleKeyEvent(KeyEvent ev) {
int eventKeyCode = ev.getKeyCode();
int eventKeyAction = ev.getAction();
if ((eventKeyAction == KeyEvent.ACTION_UP || eventKeyAction == KeyEvent.ACTION_DOWN) && KEY_EVENTS_ACTIONS.containsKey(eventKeyCode)) {
if ((eventKeyAction == KeyEvent.ACTION_UP || eventKeyAction == KeyEvent.ACTION_DOWN)
&& KEY_EVENTS_ACTIONS.containsKey(eventKeyCode)) {
dispatchEvent(KEY_EVENTS_ACTIONS.get(eventKeyCode), mLastFocusedViewId, eventKeyAction);
}
}
/**
* Called from {@link ReactRootView} when focused view changes.
*/
/** Called from {@link ReactRootView} when focused view changes. */
public void onFocusChanged(View newFocusedView) {
if (mLastFocusedViewId == newFocusedView.getId()) {
return;
@@ -77,9 +68,7 @@ public class ReactAndroidHWInputDeviceHelper {
dispatchEvent("focus", newFocusedView.getId());
}
/**
* Called from {@link ReactRootView} when the whole view hierarchy looses focus.
*/
/** Called from {@link ReactRootView} when the whole view hierarchy looses focus. */
public void clearFocus() {
if (mLastFocusedViewId != View.NO_ID) {
dispatchEvent("blur", mLastFocusedViewId);
@@ -1,16 +1,13 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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;
public interface ReactApplication {
/**
* Get the default {@link ReactNativeHost} for this app.
*/
/** Get the default {@link ReactNativeHost} for this app. */
ReactNativeHost getReactNativeHost();
}
@@ -1,21 +1,18 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.devsupport.DoubleTapReloadRecognizer;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import javax.annotation.Nullable;
/**
@@ -27,19 +24,19 @@ public class ReactDelegate {
private final Activity mActivity;
private ReactRootView mReactRootView;
@Nullable
private final String mMainComponentName;
@Nullable private final String mMainComponentName;
@Nullable
private Bundle mLaunchOptions;
@Nullable private Bundle mLaunchOptions;
@Nullable
private DoubleTapReloadRecognizer mDoubleTapReloadRecognizer;
@Nullable private DoubleTapReloadRecognizer mDoubleTapReloadRecognizer;
private ReactNativeHost mReactNativeHost;
public ReactDelegate(Activity activity, ReactNativeHost reactNativeHost, @Nullable String appKey, @Nullable Bundle launchOptions) {
public ReactDelegate(
Activity activity,
ReactNativeHost reactNativeHost,
@Nullable String appKey,
@Nullable Bundle launchOptions) {
mActivity = activity;
mMainComponentName = appKey;
mLaunchOptions = launchOptions;
@@ -50,9 +47,12 @@ public class ReactDelegate {
public void onHostResume() {
if (getReactNativeHost().hasInstance()) {
if (mActivity instanceof DefaultHardwareBackBtnHandler) {
getReactNativeHost().getReactInstanceManager().onHostResume(mActivity, (DefaultHardwareBackBtnHandler) mActivity);
getReactNativeHost()
.getReactInstanceManager()
.onHostResume(mActivity, (DefaultHardwareBackBtnHandler) mActivity);
} else {
throw new ClassCastException("Host Activity does not implement DefaultHardwareBackBtnHandler");
throw new ClassCastException(
"Host Activity does not implement DefaultHardwareBackBtnHandler");
}
}
}
@@ -81,9 +81,12 @@ public class ReactDelegate {
return false;
}
public void onActivityResult(int requestCode, int resultCode, Intent data, boolean shouldForwardToReactInstance) {
public void onActivityResult(
int requestCode, int resultCode, Intent data, boolean shouldForwardToReactInstance) {
if (getReactNativeHost().hasInstance() && shouldForwardToReactInstance) {
getReactNativeHost().getReactInstanceManager().onActivityResult(mActivity, requestCode, resultCode, data);
getReactNativeHost()
.getReactInstanceManager()
.onActivityResult(mActivity, requestCode, resultCode, data);
}
}
@@ -97,26 +100,23 @@ public class ReactDelegate {
}
mReactRootView = createRootView();
mReactRootView.startReactApplication(
getReactNativeHost().getReactInstanceManager(),
appKey,
mLaunchOptions);
getReactNativeHost().getReactInstanceManager(), appKey, mLaunchOptions);
}
public ReactRootView getReactRootView() {
return mReactRootView;
}
protected ReactRootView createRootView() {
return new ReactRootView(mActivity);
}
/**
* Handles delegating the {@link Activity#onKeyUp(int, KeyEvent)} method to determine whether
* the application should show the developer menu or should reload the React Application.
* Handles delegating the {@link Activity#onKeyUp(int, KeyEvent)} method to determine whether the
* application should show the developer menu or should reload the React Application.
*
* @return true if we consume the event and either shoed the develop menu or reloaded the application.
* @return true if we consume the event and either shoed the develop menu or reloaded the
* application.
*/
public boolean shouldShowDevMenuOrReload(int keyCode, KeyEvent event) {
if (getReactNativeHost().hasInstance() && getReactNativeHost().getUseDeveloperSupport()) {
@@ -124,7 +124,9 @@ public class ReactDelegate {
getReactNativeHost().getReactInstanceManager().showDevOptionsDialog();
return true;
}
boolean didDoubleTapR = Assertions.assertNotNull(mDoubleTapReloadRecognizer).didDoubleTapR(keyCode, mActivity.getCurrentFocus());
boolean didDoubleTapR =
Assertions.assertNotNull(mDoubleTapReloadRecognizer)
.didDoubleTapR(keyCode, mActivity.getCurrentFocus());
if (didDoubleTapR) {
getReactNativeHost().getReactInstanceManager().getDevSupportManager().handleReloadJS();
return true;
@@ -133,9 +135,7 @@ public class ReactDelegate {
return false;
}
/**
* Get the {@link ReactNativeHost} used by this app.
*/
/** Get the {@link ReactNativeHost} used by this app. */
private ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@@ -143,5 +143,4 @@ public class ReactDelegate {
public ReactInstanceManager getReactInstanceManager() {
return getReactNativeHost().getReactInstanceManager();
}
}
@@ -1,11 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
* Copyright (c) Facebook, Inc. and its affiliates.
*
* <p>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;
import android.annotation.TargetApi;
@@ -17,194 +15,188 @@ import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
import com.facebook.react.modules.core.PermissionAwareActivity;
import com.facebook.react.modules.core.PermissionListener;
import javax.annotation.Nullable;
import androidx.fragment.app.Fragment;
/**
* Fragment for creating a React View. This allows the developer to "embed" a React Application
* inside native components such as a Drawer, ViewPager, etc.
*/
* Fragment for creating a React View. This allows the developer to "embed" a React Application
* inside native components such as a Drawer, ViewPager, etc.
*/
public class ReactFragment extends Fragment implements PermissionAwareActivity {
private static final String ARG_COMPONENT_NAME = "arg_component_name";
private static final String ARG_LAUNCH_OPTIONS = "arg_launch_options";
private static final String ARG_COMPONENT_NAME = "arg_component_name";
private static final String ARG_LAUNCH_OPTIONS = "arg_launch_options";
private ReactDelegate mReactDelegate;
private ReactDelegate mReactDelegate;
@Nullable
private PermissionListener mPermissionListener;
@Nullable private PermissionListener mPermissionListener;
public ReactFragment() {
// Required empty public constructor
}
/**
* @param componentName The name of the react native component
* @return A new instance of fragment ReactFragment.
*/
private static ReactFragment newInstance(String componentName, Bundle launchOptions) {
ReactFragment fragment = new ReactFragment();
Bundle args = new Bundle();
args.putString(ARG_COMPONENT_NAME, componentName);
args.putBundle(ARG_LAUNCH_OPTIONS, launchOptions);
fragment.setArguments(args);
return fragment;
}
// region Lifecycle
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String mainComponentName = null;
Bundle launchOptions = null;
if (getArguments() != null) {
mainComponentName = getArguments().getString(ARG_COMPONENT_NAME);
launchOptions = getArguments().getBundle(ARG_LAUNCH_OPTIONS);
}
if (mainComponentName == null) {
throw new IllegalStateException("Cannot loadApp if component name is null");
}
mReactDelegate = new ReactDelegate(getActivity(), getReactNativeHost(), mainComponentName, launchOptions);
}
/**
* Get the {@link ReactNativeHost} used by this app. By default, assumes
* {@link Activity#getApplication()} is an instance of {@link ReactApplication} and calls
* {@link ReactApplication#getReactNativeHost()}. Override this method if your application class
* does not implement {@code ReactApplication} or you simply have a different mechanism for
* storing a {@code ReactNativeHost}, e.g. as a static field somewhere.
*/
protected ReactNativeHost getReactNativeHost() {
return ((ReactApplication) getActivity().getApplication()).getReactNativeHost();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mReactDelegate.loadApp();
return mReactDelegate.getReactRootView();
}
@Override
public void onResume() {
super.onResume();
mReactDelegate.onHostResume();
}
@Override
public void onPause() {
super.onPause();
mReactDelegate.onHostPause();
}
@Override
public void onDestroy() {
super.onDestroy();
mReactDelegate.onHostDestroy();
}
// endregion
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
mReactDelegate.onActivityResult(requestCode, resultCode, data, false);
}
/**
* Helper to forward hardware back presses to our React Native Host
*
* This must be called via a forward from your host Activity
*
*/
public boolean onBackPressed() {
return mReactDelegate.onBackPressed();
}
/**
* Helper to forward onKeyUp commands from our host Activity.
* This allows ReactFragment to handle double tap reloads and dev menus
*
* This must be called via a forward from your host Activity
*
* @param keyCode keyCode
* @param event event
* @return true if we handled onKeyUp
*/
public boolean onKeyUp(int keyCode, KeyEvent event) {
return mReactDelegate.shouldShowDevMenuOrReload(keyCode, event);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (mPermissionListener != null &&
mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
mPermissionListener = null;
}
}
@Override
public int checkPermission(String permission, int pid, int uid) {
return getActivity().checkPermission(permission, pid, uid);
}
@TargetApi(Build.VERSION_CODES.M)
@Override
public int checkSelfPermission(String permission) {
return getActivity().checkSelfPermission(permission);
}
@TargetApi(Build.VERSION_CODES.M)
@Override
public void requestPermissions(String[] permissions, int requestCode, PermissionListener listener) {
mPermissionListener = listener;
requestPermissions(permissions, requestCode);
}
/**
* Builder class to help instantiate a ReactFragment
*/
public static class Builder {
String mComponentName;
Bundle mLaunchOptions;
public Builder() {
mComponentName = null;
mLaunchOptions = null;
public ReactFragment() {
// Required empty public constructor
}
/**
* Set the Component name for our React Native instance.
*
* @param componentName The name of the component
* @return Builder
* @param componentName The name of the react native component
* @return A new instance of fragment ReactFragment.
*/
public Builder setComponentName(String componentName) {
mComponentName = componentName;
return this;
private static ReactFragment newInstance(String componentName, Bundle launchOptions) {
ReactFragment fragment = new ReactFragment();
Bundle args = new Bundle();
args.putString(ARG_COMPONENT_NAME, componentName);
args.putBundle(ARG_LAUNCH_OPTIONS, launchOptions);
fragment.setArguments(args);
return fragment;
}
// region Lifecycle
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String mainComponentName = null;
Bundle launchOptions = null;
if (getArguments() != null) {
mainComponentName = getArguments().getString(ARG_COMPONENT_NAME);
launchOptions = getArguments().getBundle(ARG_LAUNCH_OPTIONS);
}
if (mainComponentName == null) {
throw new IllegalStateException("Cannot loadApp if component name is null");
}
mReactDelegate =
new ReactDelegate(getActivity(), getReactNativeHost(), mainComponentName, launchOptions);
}
/**
* Set the Launch Options for our React Native instance.
*
* @param launchOptions launchOptions
* @return Builder
* Get the {@link ReactNativeHost} used by this app. By default, assumes {@link
* Activity#getApplication()} is an instance of {@link ReactApplication} and calls {@link
* ReactApplication#getReactNativeHost()}. Override this method if your application class does not
* implement {@code ReactApplication} or you simply have a different mechanism for storing a
* {@code ReactNativeHost}, e.g. as a static field somewhere.
*/
public Builder setLaunchOptions(Bundle launchOptions) {
mLaunchOptions = launchOptions;
return this;
protected ReactNativeHost getReactNativeHost() {
return ((ReactApplication) getActivity().getApplication()).getReactNativeHost();
}
public ReactFragment build() {
return ReactFragment.newInstance(mComponentName, mLaunchOptions);
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mReactDelegate.loadApp();
return mReactDelegate.getReactRootView();
}
}
@Override
public void onResume() {
super.onResume();
mReactDelegate.onHostResume();
}
@Override
public void onPause() {
super.onPause();
mReactDelegate.onHostPause();
}
@Override
public void onDestroy() {
super.onDestroy();
mReactDelegate.onHostDestroy();
}
// endregion
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
mReactDelegate.onActivityResult(requestCode, resultCode, data, false);
}
/**
* Helper to forward hardware back presses to our React Native Host
*
* <p>This must be called via a forward from your host Activity
*/
public boolean onBackPressed() {
return mReactDelegate.onBackPressed();
}
/**
* Helper to forward onKeyUp commands from our host Activity. This allows ReactFragment to handle
* double tap reloads and dev menus
*
* <p>This must be called via a forward from your host Activity
*
* @param keyCode keyCode
* @param event event
* @return true if we handled onKeyUp
*/
public boolean onKeyUp(int keyCode, KeyEvent event) {
return mReactDelegate.shouldShowDevMenuOrReload(keyCode, event);
}
@Override
public void onRequestPermissionsResult(
int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (mPermissionListener != null
&& mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
mPermissionListener = null;
}
}
@Override
public int checkPermission(String permission, int pid, int uid) {
return getActivity().checkPermission(permission, pid, uid);
}
@TargetApi(Build.VERSION_CODES.M)
@Override
public int checkSelfPermission(String permission) {
return getActivity().checkSelfPermission(permission);
}
@TargetApi(Build.VERSION_CODES.M)
@Override
public void requestPermissions(
String[] permissions, int requestCode, PermissionListener listener) {
mPermissionListener = listener;
requestPermissions(permissions, requestCode);
}
/** Builder class to help instantiate a ReactFragment */
public static class Builder {
String mComponentName;
Bundle mLaunchOptions;
public Builder() {
mComponentName = null;
mLaunchOptions = null;
}
/**
* Set the Component name for our React Native instance.
*
* @param componentName The name of the component
* @return Builder
*/
public Builder setComponentName(String componentName) {
mComponentName = componentName;
return this;
}
/**
* Set the Launch Options for our React Native instance.
*
* @param launchOptions launchOptions
* @return Builder
*/
public Builder setLaunchOptions(Bundle launchOptions) {
mLaunchOptions = launchOptions;
return this;
}
public ReactFragment build() {
return ReactFragment.newInstance(mComponentName, mLaunchOptions);
}
}
}
@@ -1,17 +1,14 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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;
/**
* @deprecated
* ReactFragmentActivity will be removed in 0.59 release.
* Use {@link ReactActivity} instead.
* @deprecated ReactFragmentActivity will be removed in 0.59 release. Use {@link ReactActivity}
* instead.
*/
@Deprecated
public abstract class ReactFragmentActivity extends ReactActivity {
}
public abstract class ReactFragmentActivity extends ReactActivity {}
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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;
import static com.facebook.infer.annotation.ThreadConfined.UI;
@@ -12,6 +11,7 @@ import static com.facebook.react.bridge.ReactMarkerConstants.ATTACH_MEASURED_ROO
import static com.facebook.react.bridge.ReactMarkerConstants.ATTACH_MEASURED_ROOT_VIEWS_START;
import static com.facebook.react.bridge.ReactMarkerConstants.BUILD_NATIVE_MODULE_REGISTRY_END;
import static com.facebook.react.bridge.ReactMarkerConstants.BUILD_NATIVE_MODULE_REGISTRY_START;
import static com.facebook.react.bridge.ReactMarkerConstants.CHANGE_THREAD_PRIORITY;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_CATALYST_INSTANCE_END;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_CATALYST_INSTANCE_START;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_REACT_CONTEXT_START;
@@ -25,7 +25,6 @@ import static com.facebook.react.bridge.ReactMarkerConstants.REACT_CONTEXT_THREA
import static com.facebook.react.bridge.ReactMarkerConstants.REACT_CONTEXT_THREAD_START;
import static com.facebook.react.bridge.ReactMarkerConstants.SETUP_REACT_CONTEXT_END;
import static com.facebook.react.bridge.ReactMarkerConstants.SETUP_REACT_CONTEXT_START;
import static com.facebook.react.bridge.ReactMarkerConstants.CHANGE_THREAD_PRIORITY;
import static com.facebook.react.bridge.ReactMarkerConstants.VM_INIT;
import static com.facebook.react.uimanager.common.UIManagerType.FABRIC;
import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_APPS;
@@ -38,9 +37,9 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Process;
import androidx.core.view.ViewCompat;
import android.util.Log;
import android.view.View;
import androidx.core.view.ViewCompat;
import com.facebook.common.logging.FLog;
import com.facebook.debug.holder.PrinterHolder;
import com.facebook.debug.tags.ReactDebugOverlayTags;
@@ -107,28 +106,26 @@ import javax.annotation.Nullable;
/**
* This class is managing instances of {@link CatalystInstance}. It exposes a way to configure
* catalyst instance using {@link ReactPackage} and keeps track of the lifecycle of that
* instance. It also sets up connection between the instance and developers support functionality
* of the framework.
* catalyst instance using {@link ReactPackage} and keeps track of the lifecycle of that instance.
* It also sets up connection between the instance and developers support functionality of the
* framework.
*
* An instance of this manager is required to start JS application in {@link ReactRootView} (see
* <p>An instance of this manager is required to start JS application in {@link ReactRootView} (see
* {@link ReactRootView#startReactApplication} for more info).
*
* The lifecycle of the instance of {@link ReactInstanceManager} should be bound to the
* activity that owns the {@link ReactRootView} that is used to render react application using this
* instance manager (see {@link ReactRootView#startReactApplication}). It's required to pass owning
* <p>The lifecycle of the instance of {@link ReactInstanceManager} should be bound to the activity
* that owns the {@link ReactRootView} that is used to render react application using this instance
* manager (see {@link ReactRootView#startReactApplication}). It's required to pass owning
* activity's lifecycle events to the instance manager (see {@link #onHostPause}, {@link
* #onHostDestroy} and {@link #onHostResume}).
*
* To instantiate an instance of this class use {@link #builder}.
* <p>To instantiate an instance of this class use {@link #builder}.
*/
@ThreadSafe
public class ReactInstanceManager {
private static final String TAG = ReactInstanceManager.class.getSimpleName();
/**
* Listener interface for react instance events.
*/
/** Listener interface for react instance events. */
public interface ReactInstanceEventListener {
/**
@@ -138,8 +135,8 @@ public class ReactInstanceManager {
void onReactContextInitialized(ReactContext context);
}
private final Set<ReactRoot> mAttachedReactRoots = Collections.synchronizedSet(
new HashSet<ReactRoot>());
private final Set<ReactRoot> mAttachedReactRoots =
Collections.synchronizedSet(new HashSet<ReactRoot>());
private volatile LifecycleState mLifecycleState;
@@ -176,8 +173,7 @@ public class ReactInstanceManager {
private final JSBundleLoader mJsBundleLoader;
public ReactContextInitParams(
JavaScriptExecutorFactory jsExecutorFactory,
JSBundleLoader jsBundleLoader) {
JavaScriptExecutorFactory jsExecutorFactory, JSBundleLoader jsBundleLoader) {
mJsExecutorFactory = Assertions.assertNotNull(jsExecutorFactory);
mJsBundleLoader = Assertions.assertNotNull(jsBundleLoader);
}
@@ -191,33 +187,31 @@ public class ReactInstanceManager {
}
}
/**
* Creates a builder that is capable of creating an instance of {@link ReactInstanceManager}.
*/
/** Creates a builder that is capable of creating an instance of {@link ReactInstanceManager}. */
public static ReactInstanceManagerBuilder builder() {
return new ReactInstanceManagerBuilder();
}
/* package */ ReactInstanceManager(
Context applicationContext,
@Nullable Activity currentActivity,
@Nullable DefaultHardwareBackBtnHandler defaultHardwareBackBtnHandler,
JavaScriptExecutorFactory javaScriptExecutorFactory,
@Nullable JSBundleLoader bundleLoader,
@Nullable String jsMainModulePath,
List<ReactPackage> packages,
boolean useDeveloperSupport,
@Nullable NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener,
LifecycleState initialLifecycleState,
@Nullable UIImplementationProvider mUIImplementationProvider,
NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler,
@Nullable RedBoxHandler redBoxHandler,
boolean lazyViewManagersEnabled,
@Nullable DevBundleDownloadListener devBundleDownloadListener,
int minNumShakes,
int minTimeLeftInFrameForNonBatchedOperationMs,
@Nullable JSIModulePackage jsiModulePackage,
@Nullable Map<String, RequestHandler> customPackagerCommandHandlers) {
Context applicationContext,
@Nullable Activity currentActivity,
@Nullable DefaultHardwareBackBtnHandler defaultHardwareBackBtnHandler,
JavaScriptExecutorFactory javaScriptExecutorFactory,
@Nullable JSBundleLoader bundleLoader,
@Nullable String jsMainModulePath,
List<ReactPackage> packages,
boolean useDeveloperSupport,
@Nullable NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener,
LifecycleState initialLifecycleState,
@Nullable UIImplementationProvider mUIImplementationProvider,
NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler,
@Nullable RedBoxHandler redBoxHandler,
boolean lazyViewManagersEnabled,
@Nullable DevBundleDownloadListener devBundleDownloadListener,
int minNumShakes,
int minTimeLeftInFrameForNonBatchedOperationMs,
@Nullable JSIModulePackage jsiModulePackage,
@Nullable Map<String, RequestHandler> customPackagerCommandHandlers) {
Log.d(ReactConstants.TAG, "ReactInstanceManager.ctor()");
initializeSoLoaderIfNecessary(applicationContext);
@@ -326,10 +320,10 @@ public class ReactInstanceManager {
/**
* Trigger react context initialization asynchronously in a background async task. This enables
* applications to pre-load the application JS, and execute global code before
* {@link ReactRootView} is available and measured.
* applications to pre-load the application JS, and execute global code before {@link
* ReactRootView} is available and measured.
*
* Called from UI thread.
* <p>Called from UI thread.
*/
@ThreadConfined(UI)
public void createReactContextInBackground() {
@@ -351,8 +345,8 @@ public class ReactInstanceManager {
public void recreateReactContextInBackground() {
Assertions.assertCondition(
mHasStartedCreatingInitialContext,
"recreateReactContextInBackground should only be called after the initial " +
"createReactContextInBackground call.");
"recreateReactContextInBackground should only be called after the initial "
+ "createReactContextInBackground call.");
recreateReactContextInBackgroundInner();
}
@@ -367,8 +361,8 @@ public class ReactInstanceManager {
final DeveloperSettings devSettings = mDevSupportManager.getDevSettings();
// If remote JS debugging is enabled, load from dev server.
if (mDevSupportManager.hasUpToDateJSBundleInCache() &&
!devSettings.isRemoteJSDebugEnabled()) {
if (mDevSupportManager.hasUpToDateJSBundleInCache()
&& !devSettings.isRemoteJSDebugEnabled()) {
// If there is a up-to-date bundle downloaded from server,
// with remote JS debugging disabled, always use that.
onJSBundleLoadedFromServer(null);
@@ -409,8 +403,8 @@ public class ReactInstanceManager {
@ThreadConfined(UI)
private void recreateReactContextInBackgroundFromBundleLoader() {
Log.d(
ReactConstants.TAG,
"ReactInstanceManager.recreateReactContextInBackgroundFromBundleLoader()");
ReactConstants.TAG,
"ReactInstanceManager.recreateReactContextInBackgroundFromBundleLoader()");
PrinterHolder.getPrinter()
.logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: load from BundleLoader");
recreateReactContextInBackground(mJavaScriptExecutorFactory, mBundleLoader);
@@ -418,7 +412,7 @@ public class ReactInstanceManager {
/**
* @return whether createReactContextInBackground has been called. Will return false after
* onDestroy until a new initial context has been created.
* onDestroy until a new initial context has been created.
*/
public boolean hasStartedCreatingInitialContext() {
return mHasStartedCreatingInitialContext;
@@ -437,7 +431,7 @@ public class ReactInstanceManager {
invokeDefaultOnBackPressed();
} else {
DeviceEventManagerModule deviceEventManagerModule =
reactContext.getNativeModule(DeviceEventManagerModule.class);
reactContext.getNativeModule(DeviceEventManagerModule.class);
deviceEventManagerModule.emitHardwareBackPressed();
}
}
@@ -449,9 +443,7 @@ public class ReactInstanceManager {
}
}
/**
* This method will give JS the opportunity to receive intents via Linking.
*/
/** This method will give JS the opportunity to receive intents via Linking. */
@ThreadConfined(UI)
public void onNewIntent(Intent intent) {
UiThreadUtil.assertOnUiThread();
@@ -464,7 +456,7 @@ public class ReactInstanceManager {
if (Intent.ACTION_VIEW.equals(action) && uri != null) {
DeviceEventManagerModule deviceEventManagerModule =
currentContext.getNativeModule(DeviceEventManagerModule.class);
currentContext.getNativeModule(DeviceEventManagerModule.class);
deviceEventManagerModule.emitNewIntentReceived(uri);
}
currentContext.onNewIntent(mCurrentActivity, intent);
@@ -501,8 +493,8 @@ public class ReactInstanceManager {
/**
* Call this from {@link Activity#onPause()}. This notifies any listening modules so they can do
* any necessary cleanup. The passed Activity is the current Activity being paused. This will
* always be the foreground activity that would be returned by
* {@link ReactContext#getCurrentActivity()}.
* always be the foreground activity that would be returned by {@link
* ReactContext#getCurrentActivity()}.
*
* @param activity the activity being paused
*/
@@ -510,23 +502,26 @@ public class ReactInstanceManager {
public void onHostPause(Activity activity) {
Assertions.assertNotNull(mCurrentActivity);
Assertions.assertCondition(
activity == mCurrentActivity,
"Pausing an activity that is not the current activity, this is incorrect! " +
"Current activity: " + mCurrentActivity.getClass().getSimpleName() + " " +
"Paused activity: " + activity.getClass().getSimpleName());
activity == mCurrentActivity,
"Pausing an activity that is not the current activity, this is incorrect! "
+ "Current activity: "
+ mCurrentActivity.getClass().getSimpleName()
+ " "
+ "Paused activity: "
+ activity.getClass().getSimpleName());
onHostPause();
}
/**
* Use this method when the activity resumes to enable invoking the back button directly from JS.
*
* This method retains an instance to provided mDefaultBackButtonImpl. Thus it's important to pass
* from the activity instance that owns this particular instance of {@link
* ReactInstanceManager}, so that once this instance receive {@link #onHostDestroy} event it
* will clear the reference to that defaultBackButtonImpl.
* <p>This method retains an instance to provided mDefaultBackButtonImpl. Thus it's important to
* pass from the activity instance that owns this particular instance of {@link
* ReactInstanceManager}, so that once this instance receive {@link #onHostDestroy} event it will
* clear the reference to that defaultBackButtonImpl.
*
* @param defaultBackButtonImpl a {@link DefaultHardwareBackBtnHandler} from an Activity that owns
* this instance of {@link ReactInstanceManager}.
* this instance of {@link ReactInstanceManager}.
*/
@ThreadConfined(UI)
public void onHostResume(Activity activity, DefaultHardwareBackBtnHandler defaultBackButtonImpl) {
@@ -536,9 +531,7 @@ public class ReactInstanceManager {
onHostResume(activity);
}
/**
* Use this method when the activity resumes.
*/
/** Use this method when the activity resumes. */
@ThreadConfined(UI)
public void onHostResume(Activity activity) {
UiThreadUtil.assertOnUiThread();
@@ -558,19 +551,20 @@ public class ReactInstanceManager {
// We check if activity is attached to window by checking if decor view is attached
final View decorView = mCurrentActivity.getWindow().getDecorView();
if (!ViewCompat.isAttachedToWindow(decorView)) {
decorView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
// we can drop listener now that we know the view is attached
decorView.removeOnAttachStateChangeListener(this);
mDevSupportManager.setDevSupportEnabled(true);
}
decorView.addOnAttachStateChangeListener(
new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
// we can drop listener now that we know the view is attached
decorView.removeOnAttachStateChangeListener(this);
mDevSupportManager.setDevSupportEnabled(true);
}
@Override
public void onViewDetachedFromWindow(View v) {
// do nothing
}
});
@Override
public void onViewDetachedFromWindow(View v) {
// do nothing
}
});
} else {
// activity is attached to window, we can enable dev support immediately
mDevSupportManager.setDevSupportEnabled(true);
@@ -612,9 +606,7 @@ public class ReactInstanceManager {
}
}
/**
* Destroy this React instance and the attached JS context.
*/
/** Destroy this React instance and the attached JS context. */
@ThreadConfined(UI)
public void destroy() {
UiThreadUtil.assertOnUiThread();
@@ -655,9 +647,9 @@ public class ReactInstanceManager {
ReactContext currentContext = getCurrentReactContext();
if (currentContext != null) {
// we currently don't have an onCreate callback so we call onResume for both transitions
if (force ||
mLifecycleState == LifecycleState.BEFORE_RESUME ||
mLifecycleState == LifecycleState.BEFORE_CREATE) {
if (force
|| mLifecycleState == LifecycleState.BEFORE_RESUME
|| mLifecycleState == LifecycleState.BEFORE_CREATE) {
currentContext.onHostResume(mCurrentActivity);
}
}
@@ -729,9 +721,9 @@ public class ReactInstanceManager {
* Attach given {@param reactRoot} to a catalyst instance manager and start JS application using
* JS module provided by {@link ReactRootView#getJSModuleName}. If the react context is currently
* being (re)-created, or if react context has not been created yet, the JS application associated
* with the provided reactRoot reactRoot will be started asynchronously, i.e this method won't block.
* This reactRoot will then be tracked by this manager and in case of catalyst instance restart it will
* be re-attached.
* with the provided reactRoot reactRoot will be started asynchronously, i.e this method won't
* block. This reactRoot will then be tracked by this manager and in case of catalyst instance
* restart it will be re-attached.
*/
@ThreadConfined(UI)
public void attachRootView(ReactRoot reactRoot) {
@@ -742,7 +734,8 @@ public class ReactInstanceManager {
clearReactRoot(reactRoot);
// If react context is being created in the background, JS application will be started
// automatically when creation completes, as reactRoot reactRoot is part of the attached reactRoot reactRoot list.
// automatically when creation completes, as reactRoot reactRoot is part of the attached
// reactRoot reactRoot list.
ReactContext currentContext = getCurrentReactContext();
if (mCreateReactContextThread == null && currentContext != null) {
attachRootViewToInstance(reactRoot);
@@ -768,9 +761,7 @@ public class ReactInstanceManager {
}
}
/**
* Uses configured {@link ReactPackage} instances to create all view managers.
*/
/** Uses configured {@link ReactPackage} instances to create all view managers. */
public List<ViewManager> getOrCreateViewManagers(
ReactApplicationContext catalystApplicationContext) {
ReactMarker.logMarker(CREATE_VIEW_MANAGERS_START);
@@ -821,7 +812,7 @@ public class ReactInstanceManager {
public @Nullable List<String> getViewManagerNames() {
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "ReactInstanceManager.getViewManagerNames");
ReactApplicationContext context;
synchronized(mReactContextLock) {
synchronized (mReactContextLock) {
context = (ReactApplicationContext) getCurrentReactContext();
if (context == null || !context.hasActiveCatalystInstance()) {
return null;
@@ -831,9 +822,10 @@ public class ReactInstanceManager {
synchronized (mPackages) {
Set<String> uniqueNames = new HashSet<>();
for (ReactPackage reactPackage : mPackages) {
SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "ReactInstanceManager.getViewManagerName")
.arg("Package", reactPackage.getClass().getSimpleName())
.flush();
SystraceMessage.beginSection(
TRACE_TAG_REACT_JAVA_BRIDGE, "ReactInstanceManager.getViewManagerName")
.arg("Package", reactPackage.getClass().getSimpleName())
.flush();
if (reactPackage instanceof ViewManagerOnDemandReactPackage) {
List<String> names =
((ViewManagerOnDemandReactPackage) reactPackage).getViewManagerNames(context);
@@ -848,16 +840,12 @@ public class ReactInstanceManager {
}
}
/**
* Add a listener to be notified of react instance events.
*/
/** Add a listener to be notified of react instance events. */
public void addReactInstanceEventListener(ReactInstanceEventListener listener) {
mReactInstanceEventListeners.add(listener);
}
/**
* Remove a listener previously added with {@link #addReactInstanceEventListener}.
*/
/** Remove a listener previously added with {@link #addReactInstanceEventListener}. */
public void removeReactInstanceEventListener(ReactInstanceEventListener listener) {
mReactInstanceEventListeners.remove(listener);
}
@@ -891,26 +879,24 @@ public class ReactInstanceManager {
private void onJSBundleLoadedFromServer(@Nullable NativeDeltaClient nativeDeltaClient) {
Log.d(ReactConstants.TAG, "ReactInstanceManager.onJSBundleLoadedFromServer()");
JSBundleLoader bundleLoader = nativeDeltaClient == null
? JSBundleLoader.createCachedBundleFromNetworkLoader(
mDevSupportManager.getSourceUrl(),
mDevSupportManager.getDownloadedJSBundleFile())
: JSBundleLoader.createDeltaFromNetworkLoader(
mDevSupportManager.getSourceUrl(), nativeDeltaClient);
JSBundleLoader bundleLoader =
nativeDeltaClient == null
? JSBundleLoader.createCachedBundleFromNetworkLoader(
mDevSupportManager.getSourceUrl(), mDevSupportManager.getDownloadedJSBundleFile())
: JSBundleLoader.createDeltaFromNetworkLoader(
mDevSupportManager.getSourceUrl(), nativeDeltaClient);
recreateReactContextInBackground(mJavaScriptExecutorFactory, bundleLoader);
}
@ThreadConfined(UI)
private void recreateReactContextInBackground(
JavaScriptExecutorFactory jsExecutorFactory,
JSBundleLoader jsBundleLoader) {
JavaScriptExecutorFactory jsExecutorFactory, JSBundleLoader jsBundleLoader) {
Log.d(ReactConstants.TAG, "ReactInstanceManager.recreateReactContextInBackground()");
UiThreadUtil.assertOnUiThread();
final ReactContextInitParams initParams = new ReactContextInitParams(
jsExecutorFactory,
jsBundleLoader);
final ReactContextInitParams initParams =
new ReactContextInitParams(jsExecutorFactory, jsBundleLoader);
if (mCreateReactContextThread == null) {
runCreateReactContextOnNewThread(initParams);
} else {
@@ -947,7 +933,8 @@ public class ReactInstanceManager {
}
}
}
// As destroy() may have run and set this to false, ensure that it is true before we create
// As destroy() may have run and set this to false, ensure that it is true before we
// create
mHasStartedCreatingInitialContext = true;
try {
@@ -1009,7 +996,6 @@ public class ReactInstanceManager {
catalystInstance.initialize();
mDevSupportManager.onNewReactContextCreated(reactContext);
mMemoryPressureRouter.addMemoryPressureListener(catalystInstance);
moveReactContextToCurrentLifecycleState();
@@ -1022,7 +1008,7 @@ public class ReactInstanceManager {
}
ReactInstanceEventListener[] listeners =
new ReactInstanceEventListener[mReactInstanceEventListeners.size()];
new ReactInstanceEventListener[mReactInstanceEventListeners.size()];
final ReactInstanceEventListener[] finalListeners =
mReactInstanceEventListeners.toArray(listeners);
@@ -1057,28 +1043,30 @@ public class ReactInstanceManager {
private void attachRootViewToInstance(final ReactRoot reactRoot) {
Log.d(ReactConstants.TAG, "ReactInstanceManager.attachRootViewToInstance()");
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "attachRootViewToInstance");
UIManager uiManager = UIManagerHelper.getUIManager(mCurrentReactContext, reactRoot.getUIManagerType());
UIManager uiManager =
UIManagerHelper.getUIManager(mCurrentReactContext, reactRoot.getUIManagerType());
@Nullable Bundle initialProperties = reactRoot.getAppProperties();
final int rootTag = uiManager.addRootView(
reactRoot.getRootViewGroup(),
initialProperties == null ?
new WritableNativeMap() : Arguments.fromBundle(initialProperties),
reactRoot.getInitialUITemplate());
final int rootTag =
uiManager.addRootView(
reactRoot.getRootViewGroup(),
initialProperties == null
? new WritableNativeMap()
: Arguments.fromBundle(initialProperties),
reactRoot.getInitialUITemplate());
reactRoot.setRootViewTag(rootTag);
if (reactRoot.getUIManagerType() == FABRIC) {
// Fabric requires to call updateRootLayoutSpecs before starting JS Application,
// this ensures the root will hace the correct pointScaleFactor.
uiManager.updateRootLayoutSpecs(rootTag, reactRoot.getWidthMeasureSpec(), reactRoot.getHeightMeasureSpec());
uiManager.updateRootLayoutSpecs(
rootTag, reactRoot.getWidthMeasureSpec(), reactRoot.getHeightMeasureSpec());
reactRoot.setShouldLogContentAppeared(true);
} else {
reactRoot.runApplication();
}
Systrace.beginAsyncSection(
TRACE_TAG_REACT_JAVA_BRIDGE,
"pre_rootView.onAttachedToReactInstance",
rootTag);
TRACE_TAG_REACT_JAVA_BRIDGE, "pre_rootView.onAttachedToReactInstance", rootTag);
UiThreadUtil.runOnUiThread(
new Runnable() {
@Override
@@ -1091,19 +1079,18 @@ public class ReactInstanceManager {
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
}
private void detachViewFromInstance(
ReactRoot reactRoot,
CatalystInstance catalystInstance) {
private void detachViewFromInstance(ReactRoot reactRoot, CatalystInstance catalystInstance) {
Log.d(ReactConstants.TAG, "ReactInstanceManager.detachViewFromInstance()");
UiThreadUtil.assertOnUiThread();
if (reactRoot.getUIManagerType() == FABRIC) {
catalystInstance.getJSModule(ReactFabric.class)
.unmountComponentAtNode(reactRoot.getRootViewTag());
catalystInstance
.getJSModule(ReactFabric.class)
.unmountComponentAtNode(reactRoot.getRootViewTag());
} else {
catalystInstance.getJSModule(AppRegistry.class)
.unmountApplicationComponentAtRootTag(reactRoot.getRootViewTag());
catalystInstance
.getJSModule(AppRegistry.class)
.unmountApplicationComponentAtRootTag(reactRoot.getRootViewTag());
}
}
private void tearDownReactContext(ReactContext reactContext) {
@@ -1124,29 +1111,28 @@ public class ReactInstanceManager {
mMemoryPressureRouter.removeMemoryPressureListener(reactContext.getCatalystInstance());
}
/**
* @return instance of {@link ReactContext} configured a {@link CatalystInstance} set
*/
/** @return instance of {@link ReactContext} configured a {@link CatalystInstance} set */
private ReactApplicationContext createReactContext(
JavaScriptExecutor jsExecutor,
JSBundleLoader jsBundleLoader) {
JavaScriptExecutor jsExecutor, JSBundleLoader jsBundleLoader) {
Log.d(ReactConstants.TAG, "ReactInstanceManager.createReactContext()");
ReactMarker.logMarker(CREATE_REACT_CONTEXT_START, jsExecutor.getName());
final ReactApplicationContext reactContext = new ReactApplicationContext(mApplicationContext);
NativeModuleCallExceptionHandler exceptionHandler = mNativeModuleCallExceptionHandler != null
? mNativeModuleCallExceptionHandler
: mDevSupportManager;
NativeModuleCallExceptionHandler exceptionHandler =
mNativeModuleCallExceptionHandler != null
? mNativeModuleCallExceptionHandler
: mDevSupportManager;
reactContext.setNativeModuleCallExceptionHandler(exceptionHandler);
NativeModuleRegistry nativeModuleRegistry = processPackages(reactContext, mPackages, false);
CatalystInstanceImpl.Builder catalystInstanceBuilder = new CatalystInstanceImpl.Builder()
.setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
.setJSExecutor(jsExecutor)
.setRegistry(nativeModuleRegistry)
.setJSBundleLoader(jsBundleLoader)
.setNativeModuleCallExceptionHandler(exceptionHandler);
CatalystInstanceImpl.Builder catalystInstanceBuilder =
new CatalystInstanceImpl.Builder()
.setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
.setJSExecutor(jsExecutor)
.setRegistry(nativeModuleRegistry)
.setJSBundleLoader(jsBundleLoader)
.setNativeModuleCallExceptionHandler(exceptionHandler);
ReactMarker.logMarker(CREATE_CATALYST_INSTANCE_START);
// CREATE_CATALYST_INSTANCE_END is in JSCExecutor.cpp
@@ -1162,11 +1148,13 @@ public class ReactInstanceManager {
reactContext.initializeWithInstance(catalystInstance);
if (mJSIModulePackage != null) {
catalystInstance.addJSIModules(mJSIModulePackage
.getJSIModules(reactContext, catalystInstance.getJavaScriptContextHolder()));
catalystInstance.addJSIModules(
mJSIModulePackage.getJSIModules(
reactContext, catalystInstance.getJavaScriptContextHolder()));
if (ReactFeatureFlags.useTurboModules) {
catalystInstance.setTurboModuleManager(catalystInstance.getJSIModule(JSIModuleType.TurboModuleManager));
catalystInstance.setTurboModuleManager(
catalystInstance.getJSIModule(JSIModuleType.TurboModuleManager));
}
}
if (mBridgeIdleDebugListener != null) {
@@ -1184,12 +1172,11 @@ public class ReactInstanceManager {
}
private NativeModuleRegistry processPackages(
ReactApplicationContext reactContext,
List<ReactPackage> packages,
boolean checkAndUpdatePackageMembership) {
NativeModuleRegistryBuilder nativeModuleRegistryBuilder = new NativeModuleRegistryBuilder(
reactContext,
this);
ReactApplicationContext reactContext,
List<ReactPackage> packages,
boolean checkAndUpdatePackageMembership) {
NativeModuleRegistryBuilder nativeModuleRegistryBuilder =
new NativeModuleRegistryBuilder(reactContext, this);
ReactMarker.logMarker(PROCESS_PACKAGES_START);
@@ -1226,11 +1213,10 @@ public class ReactInstanceManager {
}
private void processPackage(
ReactPackage reactPackage,
NativeModuleRegistryBuilder nativeModuleRegistryBuilder) {
ReactPackage reactPackage, NativeModuleRegistryBuilder nativeModuleRegistryBuilder) {
SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "processPackage")
.arg("className", reactPackage.getClass().getSimpleName())
.flush();
.arg("className", reactPackage.getClass().getSimpleName())
.flush();
if (reactPackage instanceof ReactPackageLogger) {
((ReactPackageLogger) reactPackage).startProcessPackage();
}
@@ -28,9 +28,7 @@ import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
/**
* Builder class for {@link ReactInstanceManager}
*/
/** Builder class for {@link ReactInstanceManager} */
public class ReactInstanceManagerBuilder {
private final List<ReactPackage> mPackages = new ArrayList<>();
@@ -55,37 +53,31 @@ public class ReactInstanceManagerBuilder {
private @Nullable JSIModulePackage mJSIModulesPackage;
private @Nullable Map<String, RequestHandler> mCustomPackagerCommandHandlers;
/* package protected */ ReactInstanceManagerBuilder() {
}
/* package protected */ ReactInstanceManagerBuilder() {}
/**
* Sets a provider of {@link UIImplementation}.
* Uses default provider if null is passed.
*/
/** Sets a provider of {@link UIImplementation}. Uses default provider if null is passed. */
public ReactInstanceManagerBuilder setUIImplementationProvider(
@Nullable UIImplementationProvider uiImplementationProvider) {
@Nullable UIImplementationProvider uiImplementationProvider) {
mUIImplementationProvider = uiImplementationProvider;
return this;
}
public ReactInstanceManagerBuilder setJSIModulesPackage(
@Nullable JSIModulePackage jsiModulePackage) {
@Nullable JSIModulePackage jsiModulePackage) {
mJSIModulesPackage = jsiModulePackage;
return this;
}
/**
* Factory for desired implementation of JavaScriptExecutor.
*/
/** Factory for desired implementation of JavaScriptExecutor. */
public ReactInstanceManagerBuilder setJavaScriptExecutorFactory(
@Nullable JavaScriptExecutorFactory javaScriptExecutorFactory) {
@Nullable JavaScriptExecutorFactory javaScriptExecutorFactory) {
mJavaScriptExecutorFactory = javaScriptExecutorFactory;
return this;
}
/**
* Name of the JS bundle file to be loaded from application's raw assets.
* Example: {@code "index.android.js"}
* Name of the JS bundle file to be loaded from application's raw assets. Example: {@code
* "index.android.js"}
*/
public ReactInstanceManagerBuilder setBundleAssetName(String bundleAssetName) {
mJSBundleAssetUrl = (bundleAssetName == null ? null : "assets://" + bundleAssetName);
@@ -96,7 +88,7 @@ public class ReactInstanceManagerBuilder {
/**
* Path to the JS bundle file to be loaded from the file system.
*
* Example: {@code "assets://index.android.js" or "/sdcard/main.jsbundle"}
* <p>Example: {@code "assets://index.android.js" or "/sdcard/main.jsbundle"}
*/
public ReactInstanceManagerBuilder setJSBundleFile(String jsBundleFile) {
if (jsBundleFile.startsWith("assets://")) {
@@ -108,10 +100,10 @@ public class ReactInstanceManagerBuilder {
}
/**
* Bundle loader to use when setting up JS environment. This supersedes
* prior invocations of {@link setJSBundleFile} and {@link setBundleAssetName}.
* Bundle loader to use when setting up JS environment. This supersedes prior invocations of
* {@link setJSBundleFile} and {@link setBundleAssetName}.
*
* Example: {@code JSBundleLoader.createFileLoader(application, bundleFile)}
* <p>Example: {@code JSBundleLoader.createFileLoader(application, bundleFile)}
*/
public ReactInstanceManagerBuilder setJSBundleLoader(JSBundleLoader jsBundleLoader) {
mJSBundleLoader = jsBundleLoader;
@@ -120,12 +112,9 @@ public class ReactInstanceManagerBuilder {
}
/**
* Path to your app's main module on the packager server. This is used when
* reloading JS during development. All paths are relative to the root folder
* the packager is serving files from.
* Examples:
* {@code "index.android"} or
* {@code "subdirectory/index.android"}
* Path to your app's main module on the packager server. This is used when reloading JS during
* development. All paths are relative to the root folder the packager is serving files from.
* Examples: {@code "index.android"} or {@code "subdirectory/index.android"}
*/
public ReactInstanceManagerBuilder setJSMainModulePath(String jsMainModulePath) {
mJSMainModulePath = jsMainModulePath;
@@ -143,14 +132,12 @@ public class ReactInstanceManagerBuilder {
}
public ReactInstanceManagerBuilder setBridgeIdleDebugListener(
NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener) {
NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener) {
mBridgeIdleDebugListener = bridgeIdleDebugListener;
return this;
}
/**
* Required. This must be your {@code Application} instance.
*/
/** Required. This must be your {@code Application} instance. */
public ReactInstanceManagerBuilder setApplication(Application application) {
mApplication = application;
return this;
@@ -162,15 +149,15 @@ public class ReactInstanceManagerBuilder {
}
public ReactInstanceManagerBuilder setDefaultHardwareBackBtnHandler(
DefaultHardwareBackBtnHandler defaultHardwareBackBtnHandler) {
DefaultHardwareBackBtnHandler defaultHardwareBackBtnHandler) {
mDefaultHardwareBackBtnHandler = defaultHardwareBackBtnHandler;
return this;
}
/**
* When {@code true}, developer options such as JS reloading and debugging are enabled.
* Note you still have to call {@link #showDevOptionsDialog} to show the dev menu,
* e.g. when the device Menu button is pressed.
* When {@code true}, developer options such as JS reloading and debugging are enabled. Note you
* still have to call {@link #showDevOptionsDialog} to show the dev menu, e.g. when the device
* Menu button is pressed.
*/
public ReactInstanceManagerBuilder setUseDeveloperSupport(boolean useDeveloperSupport) {
mUseDeveloperSupport = useDeveloperSupport;
@@ -182,18 +169,18 @@ public class ReactInstanceManagerBuilder {
* creation time, we wouldn't expect an onResume call until we get an onPause call.
*/
public ReactInstanceManagerBuilder setInitialLifecycleState(
LifecycleState initialLifecycleState) {
LifecycleState initialLifecycleState) {
mInitialLifecycleState = initialLifecycleState;
return this;
}
/**
* Set the exception handler for all native module calls. If not set, the default
* {@link DevSupportManager} will be used, which shows a redbox in dev mode and rethrows
* (crashes the app) in prod mode.
* Set the exception handler for all native module calls. If not set, the default {@link
* DevSupportManager} will be used, which shows a redbox in dev mode and rethrows (crashes the
* app) in prod mode.
*/
public ReactInstanceManagerBuilder setNativeModuleCallExceptionHandler(
NativeModuleCallExceptionHandler handler) {
NativeModuleCallExceptionHandler handler) {
mNativeModuleCallExceptionHandler = handler;
return this;
}
@@ -209,7 +196,7 @@ public class ReactInstanceManagerBuilder {
}
public ReactInstanceManagerBuilder setDevBundleDownloadListener(
@Nullable DevBundleDownloadListener listener) {
@Nullable DevBundleDownloadListener listener) {
mDevBundleDownloadListener = listener;
return this;
}
@@ -232,33 +219,32 @@ public class ReactInstanceManagerBuilder {
}
/**
* Instantiates a new {@link ReactInstanceManager}.
* Before calling {@code build}, the following must be called:
* Instantiates a new {@link ReactInstanceManager}. Before calling {@code build}, the following
* must be called:
*
* <ul>
* <li> {@link #setApplication}
* <li> {@link #setCurrentActivity} if the activity has already resumed
* <li> {@link #setDefaultHardwareBackBtnHandler} if the activity has already resumed
* <li> {@link #setJSBundleFile} or {@link #setJSMainModulePath}
* <li>{@link #setApplication}
* <li>{@link #setCurrentActivity} if the activity has already resumed
* <li>{@link #setDefaultHardwareBackBtnHandler} if the activity has already resumed
* <li>{@link #setJSBundleFile} or {@link #setJSMainModulePath}
* </ul>
*/
public ReactInstanceManager build() {
Assertions.assertNotNull(
mApplication,
"Application property has not been set with this builder");
mApplication, "Application property has not been set with this builder");
if (mInitialLifecycleState == LifecycleState.RESUMED) {
Assertions.assertNotNull(
mCurrentActivity,
"Activity needs to be set if initial lifecycle state is resumed");
mCurrentActivity, "Activity needs to be set if initial lifecycle state is resumed");
}
Assertions.assertCondition(
mUseDeveloperSupport || mJSBundleAssetUrl != null || mJSBundleLoader != null,
"JS Bundle File or Asset URL has to be provided when dev support is disabled");
mUseDeveloperSupport || mJSBundleAssetUrl != null || mJSBundleLoader != null,
"JS Bundle File or Asset URL has to be provided when dev support is disabled");
Assertions.assertCondition(
mJSMainModulePath != null || mJSBundleAssetUrl != null || mJSBundleLoader != null,
"Either MainModulePath or JS Bundle File needs to be provided");
mJSMainModulePath != null || mJSBundleAssetUrl != null || mJSBundleLoader != null,
"Either MainModulePath or JS Bundle File needs to be provided");
if (mUIImplementationProvider == null) {
// create default UIImplementationProvider if the provided one is null.
@@ -1,31 +1,28 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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;
import java.util.List;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import java.util.List;
/**
* A simple wrapper for ReactPackage to make it aware of its {@link ReactInstanceManager}
* when creating native modules. This is useful when the package needs to ask
* the instance manager for more information, like {@link DevSupportManager}.
* A simple wrapper for ReactPackage to make it aware of its {@link ReactInstanceManager} when
* creating native modules. This is useful when the package needs to ask the instance manager for
* more information, like {@link DevSupportManager}.
*
* TODO(t11394819): Consolidate this with LazyReactPackage
* Use {@link ReactPackage} or {@link LazyReactPackage} and inject reactInstanceManager as a part of when plugins are initialized.
* <p>TODO(t11394819): Consolidate this with LazyReactPackage Use {@link ReactPackage} or {@link
* LazyReactPackage} and inject reactInstanceManager as a part of when plugins are initialized.
*/
@Deprecated
public abstract class ReactInstancePackage implements ReactPackage {
public abstract List<NativeModule> createNativeModules(
ReactApplicationContext reactContext,
ReactInstanceManager reactInstanceManager);
ReactApplicationContext reactContext, ReactInstanceManager reactInstanceManager);
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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;
import android.app.Application;
@@ -32,9 +31,7 @@ public abstract class ReactNativeHost {
mApplication = application;
}
/**
* Get the current {@link ReactInstanceManager} instance, or create one.
*/
/** Get the current {@link ReactInstanceManager} instance, or create one. */
public ReactInstanceManager getReactInstanceManager() {
if (mReactInstanceManager == null) {
ReactMarker.logMarker(ReactMarkerConstants.GET_REACT_INSTANCE_MANAGER_START);
@@ -65,15 +62,16 @@ public abstract class ReactNativeHost {
protected ReactInstanceManager createReactInstanceManager() {
ReactMarker.logMarker(ReactMarkerConstants.BUILD_REACT_INSTANCE_MANAGER_START);
ReactInstanceManagerBuilder builder = ReactInstanceManager.builder()
.setApplication(mApplication)
.setJSMainModulePath(getJSMainModuleName())
.setUseDeveloperSupport(getUseDeveloperSupport())
.setRedBoxHandler(getRedBoxHandler())
.setJavaScriptExecutorFactory(getJavaScriptExecutorFactory())
.setUIImplementationProvider(getUIImplementationProvider())
.setJSIModulesPackage(getJSIModulePackage())
.setInitialLifecycleState(LifecycleState.BEFORE_CREATE);
ReactInstanceManagerBuilder builder =
ReactInstanceManager.builder()
.setApplication(mApplication)
.setJSMainModulePath(getJSMainModuleName())
.setUseDeveloperSupport(getUseDeveloperSupport())
.setRedBoxHandler(getRedBoxHandler())
.setJavaScriptExecutorFactory(getJavaScriptExecutorFactory())
.setUIImplementationProvider(getUIImplementationProvider())
.setJSIModulesPackage(getJSIModulePackage())
.setInitialLifecycleState(LifecycleState.BEFORE_CREATE);
for (ReactPackage reactPackage : getPackages()) {
builder.addPackage(reactPackage);
@@ -90,17 +88,12 @@ public abstract class ReactNativeHost {
return reactInstanceManager;
}
/**
* Get the {@link RedBoxHandler} to send RedBox-related callbacks to.
*/
/** Get the {@link RedBoxHandler} to send RedBox-related callbacks to. */
protected @Nullable RedBoxHandler getRedBoxHandler() {
return null;
}
/**
* Get the {@link JavaScriptExecutorFactory}. Override this to use a custom
* Executor.
*/
/** Get the {@link JavaScriptExecutorFactory}. Override this to use a custom Executor. */
protected @Nullable JavaScriptExecutorFactory getJavaScriptExecutorFactory() {
return null;
}
@@ -113,22 +106,20 @@ public abstract class ReactNativeHost {
* Get the {@link UIImplementationProvider} to use. Override this method if you want to use a
* custom UI implementation.
*
* Note: this is very advanced functionality, in 99% of cases you don't need to override this.
* <p>Note: this is very advanced functionality, in 99% of cases you don't need to override this.
*/
protected UIImplementationProvider getUIImplementationProvider() {
return new UIImplementationProvider();
}
protected @Nullable
JSIModulePackage getJSIModulePackage() {
protected @Nullable JSIModulePackage getJSIModulePackage() {
return null;
}
/**
* Returns the name of the main module. Determines the URL used to fetch the JS bundle
* from the packager server. It is only used when dev support is enabled.
* This is the first file to be executed once the {@link ReactInstanceManager} is created.
* e.g. "index.android"
* Returns the name of the main module. Determines the URL used to fetch the JS bundle from the
* packager server. It is only used when dev support is enabled. This is the first file to be
* executed once the {@link ReactInstanceManager} is created. e.g. "index.android"
*/
protected String getJSMainModuleName() {
return "index.android";
@@ -136,9 +127,8 @@ public abstract class ReactNativeHost {
/**
* Returns a custom path of the bundle file. This is used in cases the bundle should be loaded
* from a custom path. By default it is loaded from Android assets, from a path specified
* by {@link getBundleAssetName}.
* e.g. "file://sdcard/myapp_cache/index.android.bundle"
* from a custom path. By default it is loaded from Android assets, from a path specified by
* {@link getBundleAssetName}. e.g. "file://sdcard/myapp_cache/index.android.bundle"
*/
protected @Nullable String getJSBundleFile() {
return null;
@@ -146,24 +136,20 @@ public abstract class ReactNativeHost {
/**
* Returns the name of the bundle in assets. If this is null, and no file path is specified for
* the bundle, the app will only work with {@code getUseDeveloperSupport} enabled and will
* always try to load the JS bundle from the packager server.
* e.g. "index.android.bundle"
* the bundle, the app will only work with {@code getUseDeveloperSupport} enabled and will always
* try to load the JS bundle from the packager server. e.g. "index.android.bundle"
*/
protected @Nullable String getBundleAssetName() {
return "index.android.bundle";
}
/**
* Returns whether dev mode should be enabled. This enables e.g. the dev menu.
*/
/** Returns whether dev mode should be enabled. This enables e.g. the dev menu. */
public abstract boolean getUseDeveloperSupport();
/**
* Returns a list of {@link ReactPackage} used by the app.
* You'll most likely want to return at least the {@code MainReactPackage}.
* If your app uses additional views or modules besides the default ones,
* you'll want to include more packages here.
* Returns a list of {@link ReactPackage} used by the app. You'll most likely want to return at
* least the {@code MainReactPackage}. If your app uses additional views or modules besides the
* default ones, you'll want to include more packages here.
*/
protected abstract List<ReactPackage> getPackages();
}
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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;
import com.facebook.react.bridge.NativeModule;
@@ -12,21 +11,18 @@ import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.ViewManager;
import java.util.List;
import javax.annotation.Nonnull;
/**
* Main interface for providing additional capabilities to the catalyst framework by couple of
* different means:
* 1) Registering new native modules
* 2) Registering new JS modules that may be accessed from native modules or from other parts of the
* native code (requiring JS modules from the package doesn't mean it will automatically be included
* as a part of the JS bundle, so there should be a corresponding piece of code on JS side that will
* require implementation of that JS module so that it gets bundled)
* 3) Registering custom native views (view managers) and custom event types
* 4) Registering natively packaged assets/resources (e.g. images) exposed to JS
* different means: 1) Registering new native modules 2) Registering new JS modules that may be
* accessed from native modules or from other parts of the native code (requiring JS modules from
* the package doesn't mean it will automatically be included as a part of the JS bundle, so there
* should be a corresponding piece of code on JS side that will require implementation of that JS
* module so that it gets bundled) 3) Registering custom native views (view managers) and custom
* event types 4) Registering natively packaged assets/resources (e.g. images) exposed to JS
*
* TODO(6788500, 6788507): Implement support for adding custom views, events and resources
* <p>TODO(6788500, 6788507): Implement support for adding custom views, events and resources
*/
public interface ReactPackage {
@@ -37,9 +33,7 @@ public interface ReactPackage {
@Nonnull
List<NativeModule> createNativeModules(@Nonnull ReactApplicationContext reactContext);
/**
* @return a list of view managers that should be registered with {@link UIManagerModule}
*/
/** @return a list of view managers that should be registered with {@link UIManagerModule} */
@Nonnull
List<ViewManager> createViewManagers(@Nonnull ReactApplicationContext reactContext);
}
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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;
import androidx.annotation.NonNull;
@@ -5,11 +5,10 @@
package com.facebook.react;
/**
* Interface for the bridge to call for TTI start and end markers.
*/
/** Interface for the bridge to call for TTI start and end markers. */
public interface ReactPackageLogger {
void startProcessPackage();
void endProcessPackage();
}
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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;
import static com.facebook.react.uimanager.common.UIManagerType.DEFAULT;
@@ -46,8 +45,8 @@ import com.facebook.react.uimanager.DisplayMetricsHolder;
import com.facebook.react.uimanager.IllegalViewOperationException;
import com.facebook.react.uimanager.JSTouchDispatcher;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.RootView;
import com.facebook.react.uimanager.ReactRoot;
import com.facebook.react.uimanager.RootView;
import com.facebook.react.uimanager.UIManagerHelper;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.common.UIManagerType;
@@ -62,20 +61,16 @@ import javax.annotation.Nullable;
* ViewGroup#onInterceptTouchEvent} method in order to be notified about the events for all of its
* children and it's also overriding {@link ViewGroup#requestDisallowInterceptTouchEvent} to make
* sure that {@link ViewGroup#onInterceptTouchEvent} will get events even when some child view start
* intercepting it. In case when no child view is interested in handling some particular touch event,
* this view's {@link View#onTouchEvent} will still return true in order to be notified about all
* subsequent touch events related to that gesture (in case when JS code wants to handle that
* intercepting it. In case when no child view is interested in handling some particular touch
* event, this view's {@link View#onTouchEvent} will still return true in order to be notified about
* all subsequent touch events related to that gesture (in case when JS code wants to handle that
* gesture).
*/
public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
/**
* Listener interface for react root view events
*/
/** Listener interface for react root view events */
public interface ReactRootViewEventListener {
/**
* Called when the react context is attached to a ReactRootView.
*/
/** Called when the react context is attached to a ReactRootView. */
void onAttachedToReactInstance(ReactRootView rootView);
}
@@ -89,7 +84,8 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
private boolean mIsAttachedToInstance;
private boolean mShouldLogContentAppeared;
private @Nullable JSTouchDispatcher mJSTouchDispatcher;
private final ReactAndroidHWInputDeviceHelper mAndroidHWInputDeviceHelper = new ReactAndroidHWInputDeviceHelper(this);
private final ReactAndroidHWInputDeviceHelper mAndroidHWInputDeviceHelper =
new ReactAndroidHWInputDeviceHelper(this);
private boolean mWasMeasured = false;
private int mWidthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
private int mHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
@@ -135,8 +131,8 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "ReactRootView.onMeasure");
try {
boolean measureSpecsUpdated = widthMeasureSpec != mWidthMeasureSpec ||
heightMeasureSpec != mHeightMeasureSpec;
boolean measureSpecsUpdated =
widthMeasureSpec != mWidthMeasureSpec || heightMeasureSpec != mHeightMeasureSpec;
mWidthMeasureSpec = widthMeasureSpec;
mHeightMeasureSpec = heightMeasureSpec;
@@ -189,21 +185,22 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
@Override
public void onChildStartedNativeGesture(MotionEvent androidEvent) {
if (mReactInstanceManager == null || !mIsAttachedToInstance ||
mReactInstanceManager.getCurrentReactContext() == null) {
if (mReactInstanceManager == null
|| !mIsAttachedToInstance
|| mReactInstanceManager.getCurrentReactContext() == null) {
FLog.w(
ReactConstants.TAG,
"Unable to dispatch touch to JS as the catalyst instance has not been attached");
ReactConstants.TAG,
"Unable to dispatch touch to JS as the catalyst instance has not been attached");
return;
}
if (mJSTouchDispatcher == null) {
FLog.w(
ReactConstants.TAG,
"Unable to dispatch touch to JS before the dispatcher is available");
ReactConstants.TAG, "Unable to dispatch touch to JS before the dispatcher is available");
return;
}
ReactContext reactContext = mReactInstanceManager.getCurrentReactContext();
EventDispatcher eventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
EventDispatcher eventDispatcher =
reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
mJSTouchDispatcher.onChildStartedNativeGesture(androidEvent, eventDispatcher);
}
@@ -235,11 +232,12 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
@Override
public boolean dispatchKeyEvent(KeyEvent ev) {
if (mReactInstanceManager == null || !mIsAttachedToInstance ||
mReactInstanceManager.getCurrentReactContext() == null) {
if (mReactInstanceManager == null
|| !mIsAttachedToInstance
|| mReactInstanceManager.getCurrentReactContext() == null) {
FLog.w(
ReactConstants.TAG,
"Unable to handle key event as the catalyst instance has not been attached");
ReactConstants.TAG,
"Unable to handle key event as the catalyst instance has not been attached");
return super.dispatchKeyEvent(ev);
}
mAndroidHWInputDeviceHelper.handleKeyEvent(ev);
@@ -248,11 +246,12 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
@Override
protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
if (mReactInstanceManager == null || !mIsAttachedToInstance ||
mReactInstanceManager.getCurrentReactContext() == null) {
if (mReactInstanceManager == null
|| !mIsAttachedToInstance
|| mReactInstanceManager.getCurrentReactContext() == null) {
FLog.w(
ReactConstants.TAG,
"Unable to handle focus changed event as the catalyst instance has not been attached");
ReactConstants.TAG,
"Unable to handle focus changed event as the catalyst instance has not been attached");
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
return;
}
@@ -262,11 +261,12 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
@Override
public void requestChildFocus(View child, View focused) {
if (mReactInstanceManager == null || !mIsAttachedToInstance ||
mReactInstanceManager.getCurrentReactContext() == null) {
if (mReactInstanceManager == null
|| !mIsAttachedToInstance
|| mReactInstanceManager.getCurrentReactContext() == null) {
FLog.w(
ReactConstants.TAG,
"Unable to handle child focus changed event as the catalyst instance has not been attached");
ReactConstants.TAG,
"Unable to handle child focus changed event as the catalyst instance has not been attached");
super.requestChildFocus(child, focused);
return;
}
@@ -275,21 +275,22 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
}
private void dispatchJSTouchEvent(MotionEvent event) {
if (mReactInstanceManager == null || !mIsAttachedToInstance ||
mReactInstanceManager.getCurrentReactContext() == null) {
if (mReactInstanceManager == null
|| !mIsAttachedToInstance
|| mReactInstanceManager.getCurrentReactContext() == null) {
FLog.w(
ReactConstants.TAG,
"Unable to dispatch touch to JS as the catalyst instance has not been attached");
ReactConstants.TAG,
"Unable to dispatch touch to JS as the catalyst instance has not been attached");
return;
}
if (mJSTouchDispatcher == null) {
FLog.w(
ReactConstants.TAG,
"Unable to dispatch touch to JS before the dispatcher is available");
ReactConstants.TAG, "Unable to dispatch touch to JS before the dispatcher is available");
return;
}
ReactContext reactContext = mReactInstanceManager.getCurrentReactContext();
EventDispatcher eventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
EventDispatcher eventDispatcher =
reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
mJSTouchDispatcher.handleTouchEvent(event, eventDispatcher);
}
@@ -349,24 +350,23 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
return this;
}
/**
* {@see #startReactApplication(ReactInstanceManager, String, android.os.Bundle)}
*/
/** {@see #startReactApplication(ReactInstanceManager, String, android.os.Bundle)} */
public void startReactApplication(ReactInstanceManager reactInstanceManager, String moduleName) {
startReactApplication(reactInstanceManager, moduleName, null);
}
/**
* {@see #startReactApplication(ReactInstanceManager, String, android.os.Bundle, String)}
*/
public void startReactApplication(ReactInstanceManager reactInstanceManager, String moduleName, @Nullable Bundle initialProperties) {
/** {@see #startReactApplication(ReactInstanceManager, String, android.os.Bundle, String)} */
public void startReactApplication(
ReactInstanceManager reactInstanceManager,
String moduleName,
@Nullable Bundle initialProperties) {
startReactApplication(reactInstanceManager, moduleName, initialProperties, null);
}
/**
* Schedule rendering of the react component rendered by the JS application from the given JS
* module (@{param moduleName}) using provided {@param reactInstanceManager} to attach to the
* JS context of that manager. Extra parameter {@param launchOptions} can be used to pass initial
* module (@{param moduleName}) using provided {@param reactInstanceManager} to attach to the JS
* context of that manager. Extra parameter {@param launchOptions} can be used to pass initial
* properties for the react component.
*/
public void startReactApplication(
@@ -382,8 +382,8 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
// here as it may be deallocated in native after passing via JNI bridge, but we want to reuse
// it in the case of re-creating the catalyst instance
Assertions.assertCondition(
mReactInstanceManager == null,
"This root view has already been attached to a catalyst instance manager");
mReactInstanceManager == null,
"This root view has already been attached to a catalyst instance manager");
mReactInstanceManager = reactInstanceManager;
mJSModuleName = moduleName;
@@ -429,7 +429,7 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
if (reactApplicationContext != null) {
UIManagerHelper.getUIManager(reactApplicationContext, getUIManagerType())
.updateRootLayoutSpecs(getRootViewTag(), widthMeasureSpec, heightMeasureSpec);
.updateRootLayoutSpecs(getRootViewTag(), widthMeasureSpec, heightMeasureSpec);
}
}
@@ -450,7 +450,7 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
@Override
public void onStage(int stage) {
switch(stage) {
switch (stage) {
case ReactStage.ON_ATTACH_TO_INSTANCE:
onAttachedToReactInstance();
break;
@@ -498,51 +498,51 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
}
/**
* Calls into JS to start the React application. Can be called multiple times with the
* same rootTag, which will re-render the application from the root.
* Calls into JS to start the React application. Can be called multiple times with the same
* rootTag, which will re-render the application from the root.
*/
@Override
public void runApplication() {
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "ReactRootView.runApplication");
try {
if (mReactInstanceManager == null || !mIsAttachedToInstance) {
return;
}
ReactContext reactContext = mReactInstanceManager.getCurrentReactContext();
if (reactContext == null) {
return;
}
CatalystInstance catalystInstance = reactContext.getCatalystInstance();
String jsAppModuleName = getJSModuleName();
if (mUseSurface) {
// TODO call surface's runApplication
} else {
if (mWasMeasured) {
updateRootLayoutSpecs(mWidthMeasureSpec, mHeightMeasureSpec);
}
WritableNativeMap appParams = new WritableNativeMap();
appParams.putDouble("rootTag", getRootViewTag());
@Nullable Bundle appProperties = getAppProperties();
if (appProperties != null) {
appParams.putMap("initialProps", Arguments.fromBundle(appProperties));
}
mShouldLogContentAppeared = true;
catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams);
}
} finally {
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "ReactRootView.runApplication");
try {
if (mReactInstanceManager == null || !mIsAttachedToInstance) {
return;
}
ReactContext reactContext = mReactInstanceManager.getCurrentReactContext();
if (reactContext == null) {
return;
}
CatalystInstance catalystInstance = reactContext.getCatalystInstance();
String jsAppModuleName = getJSModuleName();
if (mUseSurface) {
// TODO call surface's runApplication
} else {
if (mWasMeasured) {
updateRootLayoutSpecs(mWidthMeasureSpec, mHeightMeasureSpec);
}
WritableNativeMap appParams = new WritableNativeMap();
appParams.putDouble("rootTag", getRootViewTag());
@Nullable Bundle appProperties = getAppProperties();
if (appProperties != null) {
appParams.putMap("initialProps", Arguments.fromBundle(appProperties));
}
mShouldLogContentAppeared = true;
catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams);
}
} finally {
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
}
}
/**
* Is used by unit test to setup mIsAttachedToWindow flags, that will let this
* view to be properly attached to catalyst instance by startReactApplication call
* Is used by unit test to setup mIsAttachedToWindow flags, that will let this view to be properly
* attached to catalyst instance by startReactApplication call
*/
@VisibleForTesting
/* package */ void simulateAttachForTesting() {
@@ -576,12 +576,12 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
protected void finalize() throws Throwable {
super.finalize();
Assertions.assertCondition(
!mIsAttachedToInstance,
"The application this ReactRootView was rendering was not unmounted before the " +
"ReactRootView was garbage collected. This usually means that your application is " +
"leaking large amounts of memory. To solve this, make sure to call " +
"ReactRootView#unmountReactApplication in the onDestroy() of your hosting Activity or in " +
"the onDestroyView() of your hosting Fragment.");
!mIsAttachedToInstance,
"The application this ReactRootView was rendering was not unmounted before the "
+ "ReactRootView was garbage collected. This usually means that your application is "
+ "leaking large amounts of memory. To solve this, make sure to call "
+ "ReactRootView#unmountReactApplication in the onDestroy() of your hosting Activity or in "
+ "the onDestroyView() of your hosting Fragment.");
}
public int getRootViewTag() {
@@ -594,9 +594,8 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
@Override
public void handleException(final Throwable t) {
if (mReactInstanceManager == null
|| mReactInstanceManager.getCurrentReactContext() == null) {
throw new RuntimeException(t);
if (mReactInstanceManager == null || mReactInstanceManager.getCurrentReactContext() == null) {
throw new RuntimeException(t);
}
Exception e = new IllegalViewOperationException(t.getMessage(), this, t);
@@ -619,9 +618,10 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
/* package */ void sendEvent(String eventName, @Nullable WritableMap params) {
if (mReactInstanceManager != null) {
mReactInstanceManager.getCurrentReactContext()
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, params);
mReactInstanceManager
.getCurrentReactContext()
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, params);
}
}
@@ -642,8 +642,9 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
@Override
public void onGlobalLayout() {
if (mReactInstanceManager == null || !mIsAttachedToInstance ||
mReactInstanceManager.getCurrentReactContext() == null) {
if (mReactInstanceManager == null
|| !mIsAttachedToInstance
|| mReactInstanceManager.getCurrentReactContext() == null) {
return;
}
checkForKeyboardEvents();
@@ -654,41 +655,40 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
private void checkForKeyboardEvents() {
getRootView().getWindowVisibleDisplayFrame(mVisibleViewArea);
final int heightDiff =
DisplayMetricsHolder.getWindowDisplayMetrics().heightPixels - mVisibleViewArea.bottom;
DisplayMetricsHolder.getWindowDisplayMetrics().heightPixels - mVisibleViewArea.bottom;
boolean isKeyboardShowingOrKeyboardHeightChanged =
mKeyboardHeight != heightDiff && heightDiff > mMinKeyboardHeightDetected;
mKeyboardHeight != heightDiff && heightDiff > mMinKeyboardHeightDetected;
if (isKeyboardShowingOrKeyboardHeightChanged) {
mKeyboardHeight = heightDiff;
sendEvent("keyboardDidShow",
createKeyboardEventPayload(
PixelUtil.toDIPFromPixel(mVisibleViewArea.bottom),
PixelUtil.toDIPFromPixel(mVisibleViewArea.left),
PixelUtil.toDIPFromPixel(mVisibleViewArea.width()),
PixelUtil.toDIPFromPixel(mKeyboardHeight))
);
sendEvent(
"keyboardDidShow",
createKeyboardEventPayload(
PixelUtil.toDIPFromPixel(mVisibleViewArea.bottom),
PixelUtil.toDIPFromPixel(mVisibleViewArea.left),
PixelUtil.toDIPFromPixel(mVisibleViewArea.width()),
PixelUtil.toDIPFromPixel(mKeyboardHeight)));
return;
}
boolean isKeyboardHidden =
mKeyboardHeight != 0 && heightDiff <= mMinKeyboardHeightDetected;
boolean isKeyboardHidden = mKeyboardHeight != 0 && heightDiff <= mMinKeyboardHeightDetected;
if (isKeyboardHidden) {
mKeyboardHeight = 0;
sendEvent("keyboardDidHide",
createKeyboardEventPayload(
PixelUtil.toDIPFromPixel(mVisibleViewArea.height()),
0,
PixelUtil.toDIPFromPixel(mVisibleViewArea.width()),
0
)
);
sendEvent(
"keyboardDidHide",
createKeyboardEventPayload(
PixelUtil.toDIPFromPixel(mVisibleViewArea.height()),
0,
PixelUtil.toDIPFromPixel(mVisibleViewArea.width()),
0));
}
}
private void checkForDeviceOrientationChanges() {
final int rotation =
((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay().getRotation();
((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay()
.getRotation();
if (mDeviceRotation == rotation) {
return;
}
@@ -699,9 +699,10 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
private void checkForDeviceDimensionsChanges() {
// Get current display metrics.
DisplayMetricsHolder.initDisplayMetrics(getContext());
// Check changes to both window and screen display metrics since they may not update at the same time.
if (!areMetricsEqual(mWindowMetrics, DisplayMetricsHolder.getWindowDisplayMetrics()) ||
!areMetricsEqual(mScreenMetrics, DisplayMetricsHolder.getScreenDisplayMetrics())) {
// Check changes to both window and screen display metrics since they may not update at the
// same time.
if (!areMetricsEqual(mWindowMetrics, DisplayMetricsHolder.getWindowDisplayMetrics())
|| !areMetricsEqual(mScreenMetrics, DisplayMetricsHolder.getScreenDisplayMetrics())) {
mWindowMetrics.setTo(DisplayMetricsHolder.getWindowDisplayMetrics());
mScreenMetrics.setTo(DisplayMetricsHolder.getScreenDisplayMetrics());
emitUpdateDimensionsEvent();
@@ -714,13 +715,13 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
} else {
// DisplayMetrics didn't have an equals method before API 17.
// Check all public fields manually.
return displayMetrics.widthPixels == otherMetrics.widthPixels &&
displayMetrics.heightPixels == otherMetrics.heightPixels &&
displayMetrics.density == otherMetrics.density &&
displayMetrics.densityDpi == otherMetrics.densityDpi &&
displayMetrics.scaledDensity == otherMetrics.scaledDensity &&
displayMetrics.xdpi == otherMetrics.xdpi &&
displayMetrics.ydpi == otherMetrics.ydpi;
return displayMetrics.widthPixels == otherMetrics.widthPixels
&& displayMetrics.heightPixels == otherMetrics.heightPixels
&& displayMetrics.density == otherMetrics.density
&& displayMetrics.densityDpi == otherMetrics.densityDpi
&& displayMetrics.scaledDensity == otherMetrics.scaledDensity
&& displayMetrics.xdpi == otherMetrics.xdpi
&& displayMetrics.ydpi == otherMetrics.ydpi;
}
}
@@ -766,7 +767,8 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
.emitUpdateDimensionsEvent();
}
private WritableMap createKeyboardEventPayload(double screenY, double screenX, double width, double height) {
private WritableMap createKeyboardEventPayload(
double screenY, double screenX, double width, double height) {
WritableMap keyboardEventParams = Arguments.createMap();
WritableMap endCoordinates = Arguments.createMap();
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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;
import androidx.annotation.NonNull;
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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;
import com.facebook.react.bridge.ReactApplicationContext;
@@ -17,7 +16,8 @@ public interface ViewManagerOnDemandReactPackage {
* Provides a list of names of ViewManagers with which these modules can be accessed from JS.
* Typically, this is ViewManager.getName().
*/
@Nullable List<String> getViewManagerNames(ReactApplicationContext reactContext);
@Nullable
List<String> getViewManagerNames(ReactApplicationContext reactContext);
/**
* Creates and returns a ViewManager with a specific name {@param viewManagerName}. It's up to an
* implementing package how to interpret the name.
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
import com.facebook.react.bridge.JSApplicationCausedNativeException;
@@ -21,8 +20,7 @@ import com.facebook.react.bridge.ReadableMap;
private final int[] mInputNodes;
public AdditionAnimatedNode(
ReadableMap config,
NativeAnimatedNodesManager nativeAnimatedNodesManager) {
ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager) {
mNativeAnimatedNodesManager = nativeAnimatedNodesManager;
ReadableArray inputNodes = config.getArray("input");
mInputNodes = new int[inputNodes.size()];
@@ -39,8 +37,8 @@ import com.facebook.react.bridge.ReadableMap;
if (animatedNode != null && animatedNode instanceof ValueAnimatedNode) {
mValue += ((ValueAnimatedNode) animatedNode).getValue();
} else {
throw new JSApplicationCausedNativeException("Illegal node ID set as an input for " +
"Animated.Add node");
throw new JSApplicationCausedNativeException(
"Illegal node ID set as an input for " + "Animated.Add node");
}
}
}
@@ -1,22 +1,17 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
import com.facebook.infer.annotation.Assertions;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
/**
* Base class for all Animated.js library node types that can be created on the "native" side.
*/
/** Base class for all Animated.js library node types that can be created on the "native" side. */
/*package*/ abstract class AnimatedNode {
public static final int INITIAL_BFS_COLOR = 0;
@@ -46,24 +41,19 @@ import javax.annotation.Nullable;
/**
* Subclasses may want to override this method in order to store a reference to the parent of a
* given node that can then be used to calculate current node's value in {@link #update}.
* In that case it is important to also override {@link #onDetachedFromNode} to clear that
* reference once current node gets detached.
* given node that can then be used to calculate current node's value in {@link #update}. In that
* case it is important to also override {@link #onDetachedFromNode} to clear that reference once
* current node gets detached.
*/
public void onAttachedToNode(AnimatedNode parent) {
}
public void onAttachedToNode(AnimatedNode parent) {}
/**
* See {@link #onAttachedToNode}
*/
public void onDetachedFromNode(AnimatedNode parent) {
}
/** See {@link #onAttachedToNode} */
public void onDetachedFromNode(AnimatedNode parent) {}
/**
* This method will be run on each node at most once every repetition of the animation loop. It
* will be executed on a node only when all the node's parent has already been updated. Therefore
* it can be used to calculate node's value.
*/
public void update() {
}
public void update() {}
}
@@ -1,15 +1,12 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
/**
* Interface used to listen to {@link ValueAnimatedNode} updates.
*/
/** Interface used to listen to {@link ValueAnimatedNode} updates. */
public interface AnimatedNodeValueListener {
void onValueUpdate(double value);
}
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
import com.facebook.react.bridge.Callback;
@@ -36,6 +35,6 @@ import com.facebook.react.bridge.ReadableMap;
*/
public void resetConfig(ReadableMap config) {
throw new JSApplicationCausedNativeException(
"Animation config for " + getClass().getSimpleName() + " cannot be reset");
"Animation config for " + getClass().getSimpleName() + " cannot be reset");
}
}
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
import com.facebook.react.bridge.ReadableMap;
@@ -54,9 +53,10 @@ public class DecayAnimation extends AnimationDriver {
mLastValue = mAnimatedValue.mValue;
}
final double value = mFromValue +
(mVelocity / (1 - mDeceleration)) *
(1 - Math.exp(-(1 - mDeceleration) * (frameTimeMillis - mStartFrameTimeMillis)));
final double value =
mFromValue
+ (mVelocity / (1 - mDeceleration))
* (1 - Math.exp(-(1 - mDeceleration) * (frameTimeMillis - mStartFrameTimeMillis)));
if (Math.abs(mLastValue - value) < 0.1) {
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
import com.facebook.react.bridge.JSApplicationCausedNativeException;
@@ -19,8 +18,7 @@ import com.facebook.react.bridge.ReadableMap;
private double mLastValue;
public DiffClampAnimatedNode(
ReadableMap config,
NativeAnimatedNodesManager nativeAnimatedNodesManager) {
ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager) {
mNativeAnimatedNodesManager = nativeAnimatedNodesManager;
mInputNodeTag = config.getInt("input");
mMin = config.getDouble("min");
@@ -41,9 +39,8 @@ import com.facebook.react.bridge.ReadableMap;
private double getInputNodeValue() {
AnimatedNode animatedNode = mNativeAnimatedNodesManager.getNodeById(mInputNodeTag);
if (animatedNode == null || !(animatedNode instanceof ValueAnimatedNode)) {
throw new JSApplicationCausedNativeException("Illegal node ID set as an input for " +
"Animated.DiffClamp node");
throw new JSApplicationCausedNativeException(
"Illegal node ID set as an input for " + "Animated.DiffClamp node");
}
return ((ValueAnimatedNode) animatedNode).getValue();
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
import com.facebook.react.bridge.JSApplicationCausedNativeException;
@@ -12,8 +11,8 @@ import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
/**
* Animated node which takes two or more value node as an input and outputs an in-order
* division of their values.
* Animated node which takes two or more value node as an input and outputs an in-order division of
* their values.
*/
/*package*/ class DivisionAnimatedNode extends ValueAnimatedNode {
@@ -21,8 +20,7 @@ import com.facebook.react.bridge.ReadableMap;
private final int[] mInputNodes;
public DivisionAnimatedNode(
ReadableMap config,
NativeAnimatedNodesManager nativeAnimatedNodesManager) {
ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager) {
mNativeAnimatedNodesManager = nativeAnimatedNodesManager;
ReadableArray inputNodes = config.getArray("input");
mInputNodes = new int[inputNodes.size()];
@@ -42,13 +40,13 @@ import com.facebook.react.bridge.ReadableMap;
continue;
}
if (value == 0) {
throw new JSApplicationCausedNativeException("Detected a division by zero in " +
"Animated.divide node");
throw new JSApplicationCausedNativeException(
"Detected a division by zero in " + "Animated.divide node");
}
mValue /= value;
} else {
throw new JSApplicationCausedNativeException("Illegal node ID set as an input for " +
"Animated.divide node");
throw new JSApplicationCausedNativeException(
"Illegal node ID set as an input for " + "Animated.divide node");
}
}
}
@@ -1,24 +1,19 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.events.RCTEventEmitter;
import java.util.List;
import javax.annotation.Nullable;
/**
* Handles updating a {@link ValueAnimatedNode} when an event gets dispatched.
*/
/** Handles updating a {@link ValueAnimatedNode} when an event gets dispatched. */
/* package */ class EventAnimationDriver implements RCTEventEmitter {
private List<String> mEventPath;
/* package */ ValueAnimatedNode mValueNode;
@@ -44,7 +39,8 @@ import javax.annotation.Nullable;
}
@Override
public void receiveTouches(String eventName, WritableArray touches, WritableArray changedIndices) {
public void receiveTouches(
String eventName, WritableArray touches, WritableArray changedIndices) {
throw new RuntimeException("receiveTouches is not support by native animated events");
}
}
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
import com.facebook.react.bridge.ReadableArray;
@@ -42,14 +41,14 @@ class FrameBasedAnimationDriver extends AnimationDriver {
for (int i = 0; i < numberOfFrames; i++) {
mFrames[i] = frames.getDouble(i);
}
if(config.hasKey("toValue")) {
if (config.hasKey("toValue")) {
mToValue = config.getType("toValue") == ReadableType.Number ? config.getDouble("toValue") : 0;
} else {
mToValue = 0;
}
if(config.hasKey("iterations")) {
mIterations = config.getType("iterations") == ReadableType.Number ?
config.getInt("iterations") : 1;
if (config.hasKey("iterations")) {
mIterations =
config.getType("iterations") == ReadableType.Number ? config.getInt("iterations") : 1;
} else {
mIterations = 1;
}
@@ -1,8 +1,8 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
@@ -10,17 +10,15 @@ import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableType;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
/**
* Animated node that corresponds to {@code AnimatedInterpolation} from AnimatedImplementation.js.
*
* Currently only a linear interpolation is supported on an input range of an arbitrary size.
* <p>Currently only a linear interpolation is supported on an input range of an arbitrary size.
*/
/*package*/ class InterpolationAnimatedNode extends ValueAnimatedNode {
@@ -61,7 +59,7 @@ import javax.annotation.Nullable;
break;
default:
throw new JSApplicationIllegalArgumentException(
"Invalid extrapolation type " + extrapolateLeft + "for left extrapolation");
"Invalid extrapolation type " + extrapolateLeft + "for left extrapolation");
}
}
@@ -76,7 +74,7 @@ import javax.annotation.Nullable;
break;
default:
throw new JSApplicationIllegalArgumentException(
"Invalid extrapolation type " + extrapolateRight + "for right extrapolation");
"Invalid extrapolation type " + extrapolateRight + "for right extrapolation");
}
}
@@ -91,8 +89,7 @@ import javax.annotation.Nullable;
return outputMax;
}
return outputMin + (outputMax - outputMin) *
(result - inputMin) / (inputMax - inputMin);
return outputMin + (outputMax - outputMin) * (result - inputMin) / (inputMax - inputMin);
}
/*package*/ static double interpolate(
@@ -100,17 +97,16 @@ import javax.annotation.Nullable;
double[] inputRange,
double[] outputRange,
String extrapolateLeft,
String extrapolateRight
) {
String extrapolateRight) {
int rangeIndex = findRangeIndex(value, inputRange);
return interpolate(
value,
inputRange[rangeIndex],
inputRange[rangeIndex + 1],
outputRange[rangeIndex],
outputRange[rangeIndex + 1],
extrapolateLeft,
extrapolateRight);
value,
inputRange[rangeIndex],
inputRange[rangeIndex + 1],
outputRange[rangeIndex],
outputRange[rangeIndex + 1],
extrapolateLeft,
extrapolateRight);
}
private static int findRangeIndex(double value, double[] ranges) {
@@ -228,16 +224,19 @@ import javax.annotation.Nullable;
int i = 0;
mSOutputMatcher.reset();
while (mSOutputMatcher.find()) {
double val = interpolate(value, mInputRange, mOutputs[i++], mExtrapolateLeft, mExtrapolateRight);
double val =
interpolate(value, mInputRange, mOutputs[i++], mExtrapolateLeft, mExtrapolateRight);
if (mShouldRound) {
// rgba requires that the r,g,b are integers.... so we want to round them, but we *dont* want to
// rgba requires that the r,g,b are integers.... so we want to round them, but we *dont*
// want to
// round the opacity (4th column).
boolean isAlpha = i == 4;
int rounded = (int)Math.round(isAlpha ? val * 1000 : val);
String num = isAlpha ? Double.toString((double)rounded / 1000) : Integer.toString(rounded);
int rounded = (int) Math.round(isAlpha ? val * 1000 : val);
String num =
isAlpha ? Double.toString((double) rounded / 1000) : Integer.toString(rounded);
mSOutputMatcher.appendReplacement(sb, num);
} else {
int intVal = (int)val;
int intVal = (int) val;
String num = intVal != val ? Double.toString(val) : Integer.toString(intVal);
mSOutputMatcher.appendReplacement(sb, num);
}
@@ -1,14 +1,12 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
import com.facebook.react.bridge.JSApplicationCausedNativeException;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
/*package*/ class ModulusAnimatedNode extends ValueAnimatedNode {
@@ -18,8 +16,7 @@ import com.facebook.react.bridge.ReadableMap;
private final double mModulus;
public ModulusAnimatedNode(
ReadableMap config,
NativeAnimatedNodesManager nativeAnimatedNodesManager) {
ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager) {
mNativeAnimatedNodesManager = nativeAnimatedNodesManager;
mInputNode = config.getInt("input");
mModulus = config.getDouble("modulus");
@@ -32,8 +29,8 @@ import com.facebook.react.bridge.ReadableMap;
final double value = ((ValueAnimatedNode) animatedNode).getValue();
mValue = (value % mModulus + mModulus) % mModulus;
} else {
throw new JSApplicationCausedNativeException("Illegal node ID set as an input for " +
"Animated.modulus node");
throw new JSApplicationCausedNativeException(
"Illegal node ID set as an input for " + "Animated.modulus node");
}
}
}
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
import com.facebook.react.bridge.JSApplicationCausedNativeException;
@@ -21,8 +20,7 @@ import com.facebook.react.bridge.ReadableMap;
private final int[] mInputNodes;
public MultiplicationAnimatedNode(
ReadableMap config,
NativeAnimatedNodesManager nativeAnimatedNodesManager) {
ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager) {
mNativeAnimatedNodesManager = nativeAnimatedNodesManager;
ReadableArray inputNodes = config.getArray("input");
mInputNodes = new int[inputNodes.size()];
@@ -39,8 +37,8 @@ import com.facebook.react.bridge.ReadableMap;
if (animatedNode != null && animatedNode instanceof ValueAnimatedNode) {
mValue *= ((ValueAnimatedNode) animatedNode).getValue();
} else {
throw new JSApplicationCausedNativeException("Illegal node ID set as an input for " +
"Animated.multiply node");
throw new JSApplicationCausedNativeException(
"Illegal node ID set as an input for " + "Animated.multiply node");
}
}
}
@@ -1,16 +1,11 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
import javax.annotation.Nullable;
import java.util.ArrayList;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
@@ -29,51 +24,51 @@ import com.facebook.react.uimanager.NativeViewHierarchyManager;
import com.facebook.react.uimanager.UIBlock;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.UIManagerModuleListener;
import java.util.ArrayList;
import javax.annotation.Nullable;
/**
* Module that exposes interface for creating and managing animated nodes on the "native" side.
*
* Animated.js library is based on a concept of a graph where nodes are values or transform
* <p>Animated.js library is based on a concept of a graph where nodes are values or transform
* operations (such as interpolation, addition, etc) and connection are used to describe how change
* of the value in one node can affect other nodes.
*
* Few examples of the nodes that can be created on the JS side:
* - Animated.Value is a simplest type of node with a numeric value which can be driven by an
* animation engine (spring, decay, etc) or by calling setValue on it directly from JS
* - Animated.add is a type of node that may have two or more input nodes. It outputs the sum of
* all the input node values
* - interpolate - is actually a method you can call on any node and it creates a new node that
* takes the parent node as an input and outputs its interpolated value (e.g. if you have value
* that can animate from 0 to 1 you can create interpolated node and set output range to be 0 to
* 100 and when the input node changes the output of interpolated node will multiply the values
* by 100)
* <p>Few examples of the nodes that can be created on the JS side: - Animated.Value is a simplest
* type of node with a numeric value which can be driven by an animation engine (spring, decay, etc)
* or by calling setValue on it directly from JS - Animated.add is a type of node that may have two
* or more input nodes. It outputs the sum of all the input node values - interpolate - is actually
* a method you can call on any node and it creates a new node that takes the parent node as an
* input and outputs its interpolated value (e.g. if you have value that can animate from 0 to 1 you
* can create interpolated node and set output range to be 0 to 100 and when the input node changes
* the output of interpolated node will multiply the values by 100)
*
* You can mix and chain nodes however you like and this way create nodes graph with connections
* <p>You can mix and chain nodes however you like and this way create nodes graph with connections
* between them.
*
* To map animated node values to view properties there is a special type of a node: AnimatedProps.
* It is created by AnimatedImplementation whenever you render Animated.View and stores a mapping
* from the view properties to the corresponding animated values (so it's actually also a node with
* connections to the value nodes).
* <p>To map animated node values to view properties there is a special type of a node:
* AnimatedProps. It is created by AnimatedImplementation whenever you render Animated.View and
* stores a mapping from the view properties to the corresponding animated values (so it's actually
* also a node with connections to the value nodes).
*
* Last "special" elements of the the graph are "animation drivers". Those are objects (represented
* as a graph nodes too) that based on some criteria updates attached values every frame (we have
* few types of those, e.g., spring, timing, decay). Animation objects can be "started" and
* "stopped". Those are like "pulse generators" for the rest of the nodes graph. Those pulses then
* propagate along the graph to the children nodes up to the special node type: AnimatedProps which
* then can be used to calculate property update map for a view.
* <p>Last "special" elements of the the graph are "animation drivers". Those are objects
* (represented as a graph nodes too) that based on some criteria updates attached values every
* frame (we have few types of those, e.g., spring, timing, decay). Animation objects can be
* "started" and "stopped". Those are like "pulse generators" for the rest of the nodes graph. Those
* pulses then propagate along the graph to the children nodes up to the special node type:
* AnimatedProps which then can be used to calculate property update map for a view.
*
* This class acts as a proxy between the "native" API that can be called from JS and the main class
* that coordinates all the action: {@link NativeAnimatedNodesManager}. Since all the methods from
* {@link NativeAnimatedNodesManager} need to be called from the UI thread, we we create a queue of
* animated graph operations that is then enqueued to be executed in the UI Thread at the end of the
* batch of JS->native calls (similarly to how it's handled in {@link UIManagerModule}). This
* isolates us from the problems that may be caused by concurrent updates of animated graph while UI
* thread is "executing" the animation loop.
* <p>This class acts as a proxy between the "native" API that can be called from JS and the main
* class that coordinates all the action: {@link NativeAnimatedNodesManager}. Since all the methods
* from {@link NativeAnimatedNodesManager} need to be called from the UI thread, we we create a
* queue of animated graph operations that is then enqueued to be executed in the UI Thread at the
* end of the batch of JS->native calls (similarly to how it's handled in {@link UIManagerModule}).
* This isolates us from the problems that may be caused by concurrent updates of animated graph
* while UI thread is "executing" the animation loop.
*/
@ReactModule(name = NativeAnimatedModule.NAME)
public class NativeAnimatedModule extends ReactContextBaseJavaModule implements
LifecycleEventListener, UIManagerModuleListener {
public class NativeAnimatedModule extends ReactContextBaseJavaModule
implements LifecycleEventListener, UIManagerModuleListener {
public static final String NAME = "NativeAnimatedModule";
@@ -92,23 +87,25 @@ public class NativeAnimatedModule extends ReactContextBaseJavaModule implements
super(reactContext);
mReactChoreographer = ReactChoreographer.getInstance();
mAnimatedFrameCallback = new GuardedFrameCallback(reactContext) {
@Override
protected void doFrameGuarded(final long frameTimeNanos) {
NativeAnimatedNodesManager nodesManager = getNodesManager();
if (nodesManager.hasActiveAnimations()) {
nodesManager.runUpdates(frameTimeNanos);
}
mAnimatedFrameCallback =
new GuardedFrameCallback(reactContext) {
@Override
protected void doFrameGuarded(final long frameTimeNanos) {
NativeAnimatedNodesManager nodesManager = getNodesManager();
if (nodesManager.hasActiveAnimations()) {
nodesManager.runUpdates(frameTimeNanos);
}
// TODO: Would be great to avoid adding this callback in case there are no active animations
// and no outstanding tasks on the operations queue. Apparently frame callbacks can only
// be posted from the UI thread and therefore we cannot schedule them directly from
// @ReactMethod methods
Assertions.assertNotNull(mReactChoreographer).postFrameCallback(
ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE,
mAnimatedFrameCallback);
}
};
// TODO: Would be great to avoid adding this callback in case there are no active
// animations
// and no outstanding tasks on the operations queue. Apparently frame callbacks can only
// be posted from the UI thread and therefore we cannot schedule them directly from
// @ReactMethod methods
Assertions.assertNotNull(mReactChoreographer)
.postFrameCallback(
ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, mAnimatedFrameCallback);
}
};
}
@Override
@@ -133,24 +130,26 @@ public class NativeAnimatedModule extends ReactContextBaseJavaModule implements
final ArrayList<UIThreadOperation> operations = mOperations;
mPreOperations = new ArrayList<>();
mOperations = new ArrayList<>();
uiManager.prependUIBlock(new UIBlock() {
@Override
public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) {
NativeAnimatedNodesManager nodesManager = getNodesManager();
for (UIThreadOperation operation : preOperations) {
operation.execute(nodesManager);
}
}
});
uiManager.addUIBlock(new UIBlock() {
@Override
public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) {
NativeAnimatedNodesManager nodesManager = getNodesManager();
for (UIThreadOperation operation : operations) {
operation.execute(nodesManager);
}
}
});
uiManager.prependUIBlock(
new UIBlock() {
@Override
public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) {
NativeAnimatedNodesManager nodesManager = getNodesManager();
for (UIThreadOperation operation : preOperations) {
operation.execute(nodesManager);
}
}
});
uiManager.addUIBlock(
new UIBlock() {
@Override
public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) {
NativeAnimatedNodesManager nodesManager = getNodesManager();
for (UIThreadOperation operation : operations) {
operation.execute(nodesManager);
}
}
});
}
@Override
@@ -170,7 +169,8 @@ public class NativeAnimatedModule extends ReactContextBaseJavaModule implements
private NativeAnimatedNodesManager getNodesManager() {
if (mNodesManager == null) {
UIManagerModule uiManager = getReactApplicationContext().getNativeModule(UIManagerModule.class);
UIManagerModule uiManager =
getReactApplicationContext().getNativeModule(UIManagerModule.class);
mNodesManager = new NativeAnimatedNodesManager(uiManager);
}
@@ -178,15 +178,15 @@ public class NativeAnimatedModule extends ReactContextBaseJavaModule implements
}
private void clearFrameCallback() {
Assertions.assertNotNull(mReactChoreographer).removeFrameCallback(
ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE,
mAnimatedFrameCallback);
Assertions.assertNotNull(mReactChoreographer)
.removeFrameCallback(
ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, mAnimatedFrameCallback);
}
private void enqueueFrameCallback() {
Assertions.assertNotNull(mReactChoreographer).postFrameCallback(
ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE,
mAnimatedFrameCallback);
Assertions.assertNotNull(mReactChoreographer)
.postFrameCallback(
ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, mAnimatedFrameCallback);
}
@VisibleForTesting
@@ -196,92 +196,102 @@ public class NativeAnimatedModule extends ReactContextBaseJavaModule implements
@ReactMethod
public void createAnimatedNode(final int tag, final ReadableMap config) {
mOperations.add(new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.createAnimatedNode(tag, config);
}
});
mOperations.add(
new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.createAnimatedNode(tag, config);
}
});
}
@ReactMethod
public void startListeningToAnimatedNodeValue(final int tag) {
final AnimatedNodeValueListener listener = new AnimatedNodeValueListener() {
public void onValueUpdate(double value) {
WritableMap onAnimatedValueData = Arguments.createMap();
onAnimatedValueData.putInt("tag", tag);
onAnimatedValueData.putDouble("value", value);
getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("onAnimatedValueUpdate", onAnimatedValueData);
}
};
final AnimatedNodeValueListener listener =
new AnimatedNodeValueListener() {
public void onValueUpdate(double value) {
WritableMap onAnimatedValueData = Arguments.createMap();
onAnimatedValueData.putInt("tag", tag);
onAnimatedValueData.putDouble("value", value);
getReactApplicationContext()
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("onAnimatedValueUpdate", onAnimatedValueData);
}
};
mOperations.add(new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.startListeningToAnimatedNodeValue(tag, listener);
}
});
mOperations.add(
new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.startListeningToAnimatedNodeValue(tag, listener);
}
});
}
@ReactMethod
public void stopListeningToAnimatedNodeValue(final int tag) {
mOperations.add(new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.stopListeningToAnimatedNodeValue(tag);
}
});
mOperations.add(
new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.stopListeningToAnimatedNodeValue(tag);
}
});
}
@ReactMethod
public void dropAnimatedNode(final int tag) {
mOperations.add(new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.dropAnimatedNode(tag);
}
});
mOperations.add(
new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.dropAnimatedNode(tag);
}
});
}
@ReactMethod
public void setAnimatedNodeValue(final int tag, final double value) {
mOperations.add(new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.setAnimatedNodeValue(tag, value);
}
});
mOperations.add(
new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.setAnimatedNodeValue(tag, value);
}
});
}
@ReactMethod
public void setAnimatedNodeOffset(final int tag, final double value) {
mOperations.add(new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.setAnimatedNodeOffset(tag, value);
}
});
mOperations.add(
new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.setAnimatedNodeOffset(tag, value);
}
});
}
@ReactMethod
public void flattenAnimatedNodeOffset(final int tag) {
mOperations.add(new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.flattenAnimatedNodeOffset(tag);
}
});
mOperations.add(
new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.flattenAnimatedNodeOffset(tag);
}
});
}
@ReactMethod
public void extractAnimatedNodeOffset(final int tag) {
mOperations.add(new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.extractAnimatedNodeOffset(tag);
}
});
mOperations.add(
new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.extractAnimatedNodeOffset(tag);
}
});
}
@ReactMethod
@@ -290,91 +300,99 @@ public class NativeAnimatedModule extends ReactContextBaseJavaModule implements
final int animatedNodeTag,
final ReadableMap animationConfig,
final Callback endCallback) {
mOperations.add(new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.startAnimatingNode(
animationId,
animatedNodeTag,
animationConfig,
endCallback);
}
});
mOperations.add(
new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.startAnimatingNode(
animationId, animatedNodeTag, animationConfig, endCallback);
}
});
}
@ReactMethod
public void stopAnimation(final int animationId) {
mOperations.add(new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.stopAnimation(animationId);
}
});
mOperations.add(
new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.stopAnimation(animationId);
}
});
}
@ReactMethod
public void connectAnimatedNodes(final int parentNodeTag, final int childNodeTag) {
mOperations.add(new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.connectAnimatedNodes(parentNodeTag, childNodeTag);
}
});
mOperations.add(
new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.connectAnimatedNodes(parentNodeTag, childNodeTag);
}
});
}
@ReactMethod
public void disconnectAnimatedNodes(final int parentNodeTag, final int childNodeTag) {
mOperations.add(new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.disconnectAnimatedNodes(parentNodeTag, childNodeTag);
}
});
mOperations.add(
new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.disconnectAnimatedNodes(parentNodeTag, childNodeTag);
}
});
}
@ReactMethod
public void connectAnimatedNodeToView(final int animatedNodeTag, final int viewTag) {
mOperations.add(new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.connectAnimatedNodeToView(animatedNodeTag, viewTag);
}
});
mOperations.add(
new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.connectAnimatedNodeToView(animatedNodeTag, viewTag);
}
});
}
@ReactMethod
public void disconnectAnimatedNodeFromView(final int animatedNodeTag, final int viewTag) {
mPreOperations.add(new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.restoreDefaultValues(animatedNodeTag, viewTag);
}
});
mOperations.add(new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.disconnectAnimatedNodeFromView(animatedNodeTag, viewTag);
}
});
mPreOperations.add(
new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.restoreDefaultValues(animatedNodeTag, viewTag);
}
});
mOperations.add(
new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.disconnectAnimatedNodeFromView(animatedNodeTag, viewTag);
}
});
}
@ReactMethod
public void addAnimatedEventToView(final int viewTag, final String eventName, final ReadableMap eventMapping) {
mOperations.add(new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.addAnimatedEventToView(viewTag, eventName, eventMapping);
}
});
public void addAnimatedEventToView(
final int viewTag, final String eventName, final ReadableMap eventMapping) {
mOperations.add(
new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.addAnimatedEventToView(viewTag, eventName, eventMapping);
}
});
}
@ReactMethod
public void removeAnimatedEventFromView(final int viewTag, final String eventName, final int animatedValueTag) {
mOperations.add(new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.removeAnimatedEventFromView(viewTag, eventName, animatedValueTag);
}
});
public void removeAnimatedEventFromView(
final int viewTag, final String eventName, final int animatedValueTag) {
mOperations.add(
new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.removeAnimatedEventFromView(viewTag, eventName, animatedValueTag);
}
});
}
}
@@ -1,14 +1,12 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
import android.util.SparseArray;
import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
@@ -22,7 +20,6 @@ import com.facebook.react.uimanager.IllegalViewOperationException;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.events.Event;
import com.facebook.react.uimanager.events.EventDispatcherListener;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashMap;
@@ -31,21 +28,20 @@ import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Queue;
import javax.annotation.Nullable;
/**
* This is the main class that coordinates how native animated JS implementation drives UI changes.
*
* It implements a management interface for animated nodes graph as well as implements a graph
* <p>It implements a management interface for animated nodes graph as well as implements a graph
* traversal algorithm that is run for each animation frame.
*
* For each animation frame we visit animated nodes that might've been updated as well as their
* <p>For each animation frame we visit animated nodes that might've been updated as well as their
* children that may use parent's values to update themselves. At the end of the traversal algorithm
* we expect to reach a special type of the node: PropsAnimatedNode that is then responsible for
* calculating property map which can be sent to native view hierarchy to update the view.
*
* IMPORTANT: This class should be accessed only from the UI Thread
* <p>IMPORTANT: This class should be accessed only from the UI Thread
*/
/*package*/ class NativeAnimatedNodesManager implements EventDispatcherListener {
@@ -67,7 +63,8 @@ import javax.annotation.Nullable;
mCustomEventNamesResolver = uiManager.getDirectEventNamesResolver();
}
/*package*/ @Nullable AnimatedNode getNodeById(int id) {
/*package*/ @Nullable
AnimatedNode getNodeById(int id) {
return mAnimatedNodes.get(id);
}
@@ -77,8 +74,8 @@ import javax.annotation.Nullable;
public void createAnimatedNode(int tag, ReadableMap config) {
if (mAnimatedNodes.get(tag) != null) {
throw new JSApplicationIllegalArgumentException("Animated node with tag " + tag +
" already exists");
throw new JSApplicationIllegalArgumentException(
"Animated node with tag " + tag + " already exists");
}
String type = config.getString("type");
final AnimatedNode node;
@@ -122,8 +119,8 @@ import javax.annotation.Nullable;
public void startListeningToAnimatedNodeValue(int tag, AnimatedNodeValueListener listener) {
AnimatedNode node = mAnimatedNodes.get(tag);
if (node == null || !(node instanceof ValueAnimatedNode)) {
throw new JSApplicationIllegalArgumentException("Animated node with tag " + tag +
" does not exists or is not a 'value' node");
throw new JSApplicationIllegalArgumentException(
"Animated node with tag " + tag + " does not exists or is not a 'value' node");
}
((ValueAnimatedNode) node).setValueListener(listener);
}
@@ -131,8 +128,8 @@ import javax.annotation.Nullable;
public void stopListeningToAnimatedNodeValue(int tag) {
AnimatedNode node = mAnimatedNodes.get(tag);
if (node == null || !(node instanceof ValueAnimatedNode)) {
throw new JSApplicationIllegalArgumentException("Animated node with tag " + tag +
" does not exists or is not a 'value' node");
throw new JSApplicationIllegalArgumentException(
"Animated node with tag " + tag + " does not exists or is not a 'value' node");
}
((ValueAnimatedNode) node).setValueListener(null);
}
@@ -140,8 +137,8 @@ import javax.annotation.Nullable;
public void setAnimatedNodeValue(int tag, double value) {
AnimatedNode node = mAnimatedNodes.get(tag);
if (node == null || !(node instanceof ValueAnimatedNode)) {
throw new JSApplicationIllegalArgumentException("Animated node with tag " + tag +
" does not exists or is not a 'value' node");
throw new JSApplicationIllegalArgumentException(
"Animated node with tag " + tag + " does not exists or is not a 'value' node");
}
stopAnimationsForNode(node);
((ValueAnimatedNode) node).mValue = value;
@@ -151,8 +148,8 @@ import javax.annotation.Nullable;
public void setAnimatedNodeOffset(int tag, double offset) {
AnimatedNode node = mAnimatedNodes.get(tag);
if (node == null || !(node instanceof ValueAnimatedNode)) {
throw new JSApplicationIllegalArgumentException("Animated node with tag " + tag +
" does not exists or is not a 'value' node");
throw new JSApplicationIllegalArgumentException(
"Animated node with tag " + tag + " does not exists or is not a 'value' node");
}
((ValueAnimatedNode) node).mOffset = offset;
mUpdatedNodes.put(tag, node);
@@ -161,8 +158,8 @@ import javax.annotation.Nullable;
public void flattenAnimatedNodeOffset(int tag) {
AnimatedNode node = mAnimatedNodes.get(tag);
if (node == null || !(node instanceof ValueAnimatedNode)) {
throw new JSApplicationIllegalArgumentException("Animated node with tag " + tag +
" does not exists or is not a 'value' node");
throw new JSApplicationIllegalArgumentException(
"Animated node with tag " + tag + " does not exists or is not a 'value' node");
}
((ValueAnimatedNode) node).flattenOffset();
}
@@ -170,25 +167,22 @@ import javax.annotation.Nullable;
public void extractAnimatedNodeOffset(int tag) {
AnimatedNode node = mAnimatedNodes.get(tag);
if (node == null || !(node instanceof ValueAnimatedNode)) {
throw new JSApplicationIllegalArgumentException("Animated node with tag " + tag +
" does not exists or is not a 'value' node");
throw new JSApplicationIllegalArgumentException(
"Animated node with tag " + tag + " does not exists or is not a 'value' node");
}
((ValueAnimatedNode) node).extractOffset();
}
public void startAnimatingNode(
int animationId,
int animatedNodeTag,
ReadableMap animationConfig,
Callback endCallback) {
int animationId, int animatedNodeTag, ReadableMap animationConfig, Callback endCallback) {
AnimatedNode node = mAnimatedNodes.get(animatedNodeTag);
if (node == null) {
throw new JSApplicationIllegalArgumentException("Animated node with tag " + animatedNodeTag +
" does not exists");
throw new JSApplicationIllegalArgumentException(
"Animated node with tag " + animatedNodeTag + " does not exists");
}
if (!(node instanceof ValueAnimatedNode)) {
throw new JSApplicationIllegalArgumentException("Animated node should be of type " +
ValueAnimatedNode.class.getName());
throw new JSApplicationIllegalArgumentException(
"Animated node should be of type " + ValueAnimatedNode.class.getName());
}
final AnimationDriver existingDriver = mActiveAnimations.get(animationId);
@@ -263,13 +257,13 @@ import javax.annotation.Nullable;
public void connectAnimatedNodes(int parentNodeTag, int childNodeTag) {
AnimatedNode parentNode = mAnimatedNodes.get(parentNodeTag);
if (parentNode == null) {
throw new JSApplicationIllegalArgumentException("Animated node with tag " + parentNodeTag +
" does not exists");
throw new JSApplicationIllegalArgumentException(
"Animated node with tag " + parentNodeTag + " does not exists");
}
AnimatedNode childNode = mAnimatedNodes.get(childNodeTag);
if (childNode == null) {
throw new JSApplicationIllegalArgumentException("Animated node with tag " + childNodeTag +
" does not exists");
throw new JSApplicationIllegalArgumentException(
"Animated node with tag " + childNodeTag + " does not exists");
}
parentNode.addChild(childNode);
mUpdatedNodes.put(childNodeTag, childNode);
@@ -278,13 +272,13 @@ import javax.annotation.Nullable;
public void disconnectAnimatedNodes(int parentNodeTag, int childNodeTag) {
AnimatedNode parentNode = mAnimatedNodes.get(parentNodeTag);
if (parentNode == null) {
throw new JSApplicationIllegalArgumentException("Animated node with tag " + parentNodeTag +
" does not exists");
throw new JSApplicationIllegalArgumentException(
"Animated node with tag " + parentNodeTag + " does not exists");
}
AnimatedNode childNode = mAnimatedNodes.get(childNodeTag);
if (childNode == null) {
throw new JSApplicationIllegalArgumentException("Animated node with tag " + childNodeTag +
" does not exists");
throw new JSApplicationIllegalArgumentException(
"Animated node with tag " + childNodeTag + " does not exists");
}
parentNode.removeChild(childNode);
mUpdatedNodes.put(childNodeTag, childNode);
@@ -293,12 +287,14 @@ import javax.annotation.Nullable;
public void connectAnimatedNodeToView(int animatedNodeTag, int viewTag) {
AnimatedNode node = mAnimatedNodes.get(animatedNodeTag);
if (node == null) {
throw new JSApplicationIllegalArgumentException("Animated node with tag " + animatedNodeTag +
" does not exists");
throw new JSApplicationIllegalArgumentException(
"Animated node with tag " + animatedNodeTag + " does not exists");
}
if (!(node instanceof PropsAnimatedNode)) {
throw new JSApplicationIllegalArgumentException("Animated node connected to view should be" +
"of type " + PropsAnimatedNode.class.getName());
throw new JSApplicationIllegalArgumentException(
"Animated node connected to view should be"
+ "of type "
+ PropsAnimatedNode.class.getName());
}
PropsAnimatedNode propsAnimatedNode = (PropsAnimatedNode) node;
propsAnimatedNode.connectToView(viewTag);
@@ -308,12 +304,14 @@ import javax.annotation.Nullable;
public void disconnectAnimatedNodeFromView(int animatedNodeTag, int viewTag) {
AnimatedNode node = mAnimatedNodes.get(animatedNodeTag);
if (node == null) {
throw new JSApplicationIllegalArgumentException("Animated node with tag " + animatedNodeTag +
" does not exists");
throw new JSApplicationIllegalArgumentException(
"Animated node with tag " + animatedNodeTag + " does not exists");
}
if (!(node instanceof PropsAnimatedNode)) {
throw new JSApplicationIllegalArgumentException("Animated node connected to view should be" +
"of type " + PropsAnimatedNode.class.getName());
throw new JSApplicationIllegalArgumentException(
"Animated node connected to view should be"
+ "of type "
+ PropsAnimatedNode.class.getName());
}
PropsAnimatedNode propsAnimatedNode = (PropsAnimatedNode) node;
propsAnimatedNode.disconnectFromView(viewTag);
@@ -329,8 +327,10 @@ import javax.annotation.Nullable;
return;
}
if (!(node instanceof PropsAnimatedNode)) {
throw new JSApplicationIllegalArgumentException("Animated node connected to view should be" +
"of type " + PropsAnimatedNode.class.getName());
throw new JSApplicationIllegalArgumentException(
"Animated node connected to view should be"
+ "of type "
+ PropsAnimatedNode.class.getName());
}
PropsAnimatedNode propsAnimatedNode = (PropsAnimatedNode) node;
propsAnimatedNode.restoreDefaultValues();
@@ -340,12 +340,14 @@ import javax.annotation.Nullable;
int nodeTag = eventMapping.getInt("animatedValueTag");
AnimatedNode node = mAnimatedNodes.get(nodeTag);
if (node == null) {
throw new JSApplicationIllegalArgumentException("Animated node with tag " + nodeTag +
" does not exists");
throw new JSApplicationIllegalArgumentException(
"Animated node with tag " + nodeTag + " does not exists");
}
if (!(node instanceof ValueAnimatedNode)) {
throw new JSApplicationIllegalArgumentException("Animated node connected to event should be" +
"of type " + ValueAnimatedNode.class.getName());
throw new JSApplicationIllegalArgumentException(
"Animated node connected to event should be"
+ "of type "
+ ValueAnimatedNode.class.getName());
}
ReadableArray path = eventMapping.getArray("nativeEventPath");
@@ -390,12 +392,13 @@ import javax.annotation.Nullable;
if (UiThreadUtil.isOnUiThread()) {
handleEvent(event);
} else {
UiThreadUtil.runOnUiThread(new Runnable() {
@Override
public void run() {
handleEvent(event);
}
});
UiThreadUtil.runOnUiThread(
new Runnable() {
@Override
public void run() {
handleEvent(event);
}
});
}
}
@@ -417,12 +420,12 @@ import javax.annotation.Nullable;
}
/**
* Animation loop performs two BFSes over the graph of animated nodes. We use incremented
* {@code mAnimatedGraphBFSColor} to mark nodes as visited in each of the BFSes which saves
* additional loops for clearing "visited" states.
* Animation loop performs two BFSes over the graph of animated nodes. We use incremented {@code
* mAnimatedGraphBFSColor} to mark nodes as visited in each of the BFSes which saves additional
* loops for clearing "visited" states.
*
* First BFS starts with nodes that are in {@code mUpdatedNodes} (that is, their value have been
* modified from JS in the last batch of JS operations) or directly attached to an active
* <p>First BFS starts with nodes that are in {@code mUpdatedNodes} (that is, their value have
* been modified from JS in the last batch of JS operations) or directly attached to an active
* animation (hence linked to objects from {@code mActiveAnimations}). In that step we calculate
* an attribute {@code mActiveIncomingNodes}. The second BFS runs in topological order over the
* sub-graph of *active* nodes. This is done by adding node to the BFS queue only if all its
@@ -543,14 +546,20 @@ import javax.annotation.Nullable;
try {
((PropsAnimatedNode) nextNode).updateView();
} catch (IllegalViewOperationException e) {
// An exception is thrown if the view hasn't been created yet. This can happen because views are
// created in batches. If this particular view didn't make it into a batch yet, the view won't
// exist and an exception will be thrown when attempting to start an animation on it.
//
// Eat the exception rather than crashing. The impact is that we may drop one or more frames of the
// animation.
FLog.e(ReactConstants.TAG, "Native animation workaround, frame lost as result of race condition", e);
}
// An exception is thrown if the view hasn't been created yet. This can happen because
// views are
// created in batches. If this particular view didn't make it into a batch yet, the view
// won't
// exist and an exception will be thrown when attempting to start an animation on it.
//
// Eat the exception rather than crashing. The impact is that we may drop one or more
// frames of the
// animation.
FLog.e(
ReactConstants.TAG,
"Native animation workaround, frame lost as result of race condition",
e);
}
}
if (nextNode instanceof ValueAnimatedNode) {
// Potentially send events to JS when the node's value is updated
@@ -574,8 +583,11 @@ import javax.annotation.Nullable;
// visited in the step above so that all the nodes properties `mActiveIncomingNodes` are set to
// zero
if (activeNodesCount != updatedNodesCount) {
throw new IllegalStateException("Looks like animated nodes graph has cycles, there are "
+ activeNodesCount + " but toposort visited only " + updatedNodesCount);
throw new IllegalStateException(
"Looks like animated nodes graph has cycles, there are "
+ activeNodesCount
+ " but toposort visited only "
+ updatedNodesCount);
}
}
}
@@ -1,27 +1,24 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
import com.facebook.react.bridge.JavaOnlyMap;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
import com.facebook.react.bridge.UIManager;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
/**
* Animated node that represents view properties. There is a special handling logic implemented for
* the nodes of this type in {@link NativeAnimatedNodesManager} that is responsible for extracting
* a map of updated properties, which can be then passed down to the view.
* the nodes of this type in {@link NativeAnimatedNodesManager} that is responsible for extracting a
* map of updated properties, which can be then passed down to the view.
*/
/*package*/ class PropsAnimatedNode extends AnimatedNode {
@@ -31,7 +28,10 @@ import javax.annotation.Nullable;
private final Map<String, Integer> mPropNodeMapping;
private final JavaOnlyMap mPropMap;
PropsAnimatedNode(ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager, UIManager uiManager) {
PropsAnimatedNode(
ReadableMap config,
NativeAnimatedNodesManager nativeAnimatedNodesManager,
UIManager uiManager) {
ReadableMap props = config.getMap("props");
ReadableMapKeySetIterator iter = props.keySetIterator();
mPropNodeMapping = new HashMap<>();
@@ -47,16 +47,17 @@ import javax.annotation.Nullable;
public void connectToView(int viewTag) {
if (mConnectedViewTag != -1) {
throw new JSApplicationIllegalArgumentException("Animated node " + mTag + " is " +
"already attached to a view");
throw new JSApplicationIllegalArgumentException(
"Animated node " + mTag + " is " + "already attached to a view");
}
mConnectedViewTag = viewTag;
}
public void disconnectFromView(int viewTag) {
if (mConnectedViewTag != viewTag) {
throw new JSApplicationIllegalArgumentException("Attempting to disconnect view that has " +
"not been connected with the given animated node");
throw new JSApplicationIllegalArgumentException(
"Attempting to disconnect view that has "
+ "not been connected with the given animated node");
}
mConnectedViewTag = -1;
@@ -64,13 +65,11 @@ import javax.annotation.Nullable;
public void restoreDefaultValues() {
ReadableMapKeySetIterator it = mPropMap.keySetIterator();
while(it.hasNextKey()) {
while (it.hasNextKey()) {
mPropMap.putNull(it.nextKey());
}
mUIManager.synchronouslyUpdateViewOnUIThread(
mConnectedViewTag,
mPropMap);
mUIManager.synchronouslyUpdateViewOnUIThread(mConnectedViewTag, mPropMap);
}
public final void updateView() {
@@ -86,18 +85,16 @@ import javax.annotation.Nullable;
} else if (node instanceof ValueAnimatedNode) {
Object animatedObject = ((ValueAnimatedNode) node).getAnimatedObject();
if (animatedObject instanceof String) {
mPropMap.putString(entry.getKey(), (String)animatedObject);
mPropMap.putString(entry.getKey(), (String) animatedObject);
} else {
mPropMap.putDouble(entry.getKey(), ((ValueAnimatedNode) node).getValue());
}
} else {
throw new IllegalArgumentException("Unsupported type of node used in property node " +
node.getClass());
throw new IllegalArgumentException(
"Unsupported type of node used in property node " + node.getClass());
}
}
mUIManager.synchronouslyUpdateViewOnUIThread(
mConnectedViewTag,
mPropMap);
mUIManager.synchronouslyUpdateViewOnUIThread(mConnectedViewTag, mPropMap);
}
}
@@ -1,18 +1,17 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
import com.facebook.react.bridge.ReadableMap;
/**
* Implementation of {@link AnimationDriver} providing support for spring animations. The
* implementation has been copied from android implementation of Rebound library (see
* <a href="http://facebook.github.io/rebound/">http://facebook.github.io/rebound/</a>)
* implementation has been copied from android implementation of Rebound library (see <a
* href="http://facebook.github.io/rebound/">http://facebook.github.io/rebound/</a>)
*/
/*package*/ class SpringAnimation extends AnimationDriver {
@@ -101,6 +100,7 @@ import com.facebook.react.bridge.ReadableMap;
/**
* get the displacement from rest for a given physics state
*
* @param state the state to measure from
* @return the distance displaced by
*/
@@ -110,22 +110,24 @@ import com.facebook.react.bridge.ReadableMap;
/**
* check if the current state is at rest
*
* @return is the spring at rest
*/
private boolean isAtRest() {
return Math.abs(mCurrentState.velocity) <= mRestSpeedThreshold &&
(getDisplacementDistanceForState(mCurrentState) <= mDisplacementFromRestThreshold ||
mSpringStiffness == 0);
return Math.abs(mCurrentState.velocity) <= mRestSpeedThreshold
&& (getDisplacementDistanceForState(mCurrentState) <= mDisplacementFromRestThreshold
|| mSpringStiffness == 0);
}
/**
* Check if the spring is overshooting beyond its target.
*
* @return true if the spring is overshooting its target
*/
private boolean isOvershooting() {
return mSpringStiffness > 0 &&
((mStartValue < mEndValue && mCurrentState.position > mEndValue) ||
(mStartValue > mEndValue && mCurrentState.position < mEndValue));
return mSpringStiffness > 0
&& ((mStartValue < mEndValue && mCurrentState.position > mEndValue)
|| (mStartValue > mEndValue && mCurrentState.position < mEndValue));
}
private void advance(double realDeltaTime) {
@@ -147,7 +149,7 @@ import com.facebook.react.bridge.ReadableMap;
double k = mSpringStiffness;
double v0 = -mInitialVelocity;
double zeta = c / (2 * Math.sqrt(k * m ));
double zeta = c / (2 * Math.sqrt(k * m));
double omega0 = Math.sqrt(k / m);
double omega1 = omega0 * Math.sqrt(1.0 - (zeta * zeta));
double x0 = mEndValue - mStartValue;
@@ -159,27 +161,26 @@ import com.facebook.react.bridge.ReadableMap;
// Under damped
double envelope = Math.exp(-zeta * omega0 * t);
position =
mEndValue -
envelope *
((v0 + zeta * omega0 * x0) / omega1 * Math.sin(omega1 * t) +
x0 * Math.cos(omega1 * t));
mEndValue
- envelope
* ((v0 + zeta * omega0 * x0) / omega1 * Math.sin(omega1 * t)
+ x0 * Math.cos(omega1 * t));
// This looks crazy -- it's actually just the derivative of the
// oscillation function
velocity =
zeta *
omega0 *
envelope *
(Math.sin(omega1 * t) * (v0 + zeta * omega0 * x0) / omega1 +
x0 * Math.cos(omega1 * t)) -
envelope *
(Math.cos(omega1 * t) * (v0 + zeta * omega0 * x0) -
omega1 * x0 * Math.sin(omega1 * t));
zeta
* omega0
* envelope
* (Math.sin(omega1 * t) * (v0 + zeta * omega0 * x0) / omega1
+ x0 * Math.cos(omega1 * t))
- envelope
* (Math.cos(omega1 * t) * (v0 + zeta * omega0 * x0)
- omega1 * x0 * Math.sin(omega1 * t));
} else {
// Critically damped spring
double envelope = Math.exp(-omega0 * t);
position = mEndValue - envelope * (x0 + (v0 + omega0 * x0) * t);
velocity =
envelope * (v0 * (t * omega0 - 1) + t * x0 * (omega0 * omega0));
velocity = envelope * (v0 * (t * omega0 - 1) + t * x0 * (omega0 * omega0));
}
mCurrentState.position = position;
@@ -1,19 +1,16 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
import com.facebook.react.bridge.JavaOnlyMap;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
/**
@@ -46,8 +43,8 @@ import javax.annotation.Nullable;
} else if (node instanceof ValueAnimatedNode) {
propsMap.putDouble(entry.getKey(), ((ValueAnimatedNode) node).getValue());
} else {
throw new IllegalArgumentException("Unsupported type of node used in property node " +
node.getClass());
throw new IllegalArgumentException(
"Unsupported type of node used in property node " + node.getClass());
}
}
}
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
import com.facebook.react.bridge.JSApplicationCausedNativeException;
@@ -21,8 +20,7 @@ import com.facebook.react.bridge.ReadableMap;
private final int[] mInputNodes;
public SubtractionAnimatedNode(
ReadableMap config,
NativeAnimatedNodesManager nativeAnimatedNodesManager) {
ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager) {
mNativeAnimatedNodesManager = nativeAnimatedNodesManager;
ReadableArray inputNodes = config.getArray("input");
mInputNodes = new int[inputNodes.size()];
@@ -43,8 +41,8 @@ import com.facebook.react.bridge.ReadableMap;
}
mValue -= ((ValueAnimatedNode) animatedNode).getValue();
} else {
throw new JSApplicationCausedNativeException("Illegal node ID set as an input for " +
"Animated.subtract node");
throw new JSApplicationCausedNativeException(
"Illegal node ID set as an input for " + "Animated.subtract node");
}
}
}
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
import com.facebook.react.bridge.JavaOnlyMap;
@@ -30,6 +29,7 @@ import com.facebook.react.bridge.ReadableMap;
public void update() {
AnimatedNode toValue = mNativeAnimatedNodesManager.getNodeById(mToValueNode);
mAnimationConfig.putDouble("toValue", ((ValueAnimatedNode) toValue).getValue());
mNativeAnimatedNodesManager.startAnimatingNode(mAnimationId, mValueNode, mAnimationConfig, null);
mNativeAnimatedNodesManager.startAnimatingNode(
mAnimationId, mValueNode, mAnimationConfig, null);
}
}
@@ -1,22 +1,21 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
import com.facebook.react.bridge.JavaOnlyArray;
import com.facebook.react.bridge.JavaOnlyMap;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import java.util.ArrayList;
import java.util.List;
/**
* Native counterpart of transform animated node (see AnimatedTransform class in AnimatedImplementation.js)
* Native counterpart of transform animated node (see AnimatedTransform class in
* AnimatedImplementation.js)
*/
/* package */ class TransformAnimatedNode extends AnimatedNode {
@@ -70,8 +69,8 @@ import java.util.List;
} else if (node instanceof ValueAnimatedNode) {
value = ((ValueAnimatedNode) node).getValue();
} else {
throw new IllegalArgumentException("Unsupported type of node used as a transform child " +
"node " + node.getClass());
throw new IllegalArgumentException(
"Unsupported type of node used as a transform child " + "node " + node.getClass());
}
} else {
value = ((StaticTransformConfig) transformConfig).mValue;
@@ -1,14 +1,12 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.animated;
import com.facebook.react.bridge.ReadableMap;
import javax.annotation.Nullable;
/**
@@ -14,13 +14,9 @@ import android.content.Intent;
*/
public interface ActivityEventListener {
/**
* Called when host (activity/service) receives an {@link Activity#onActivityResult} call.
*/
/** Called when host (activity/service) receives an {@link Activity#onActivityResult} call. */
void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data);
/**
* Called when a new intent is passed to the activity
*/
/** Called when a new intent is passed to the activity */
void onNewIntent(Intent intent);
}
@@ -1,30 +1,27 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import android.os.Bundle;
import java.lang.reflect.Array;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import android.os.Bundle;
public class Arguments {
private static Object makeNativeObject(Object object) {
if (object == null) {
return null;
} else if (object instanceof Float ||
object instanceof Long ||
object instanceof Byte ||
object instanceof Short) {
} else if (object instanceof Float
|| object instanceof Long
|| object instanceof Byte
|| object instanceof Short) {
return ((Number) object).doubleValue();
} else if (object.getClass().isArray()) {
return makeNativeArray(object);
@@ -41,12 +38,11 @@ public class Arguments {
}
/**
* This method converts a List into a NativeArray. The data types supported
* are boolean, int, float, double, and String. List, Map, and Bundle
* objects, as well as arrays, containing values of the above types and/or
* null, or any recursive arrangement of these, are also supported. The best
* way to think of this is a way to generate a Java representation of a json
* list, from Java types which have a natural representation in json.
* This method converts a List into a NativeArray. The data types supported are boolean, int,
* float, double, and String. List, Map, and Bundle objects, as well as arrays, containing values
* of the above types and/or null, or any recursive arrangement of these, are also supported. The
* best way to think of this is a way to generate a Java representation of a json list, from Java
* types which have a natural representation in json.
*/
public static WritableNativeArray makeNativeArray(List objects) {
WritableNativeArray nativeArray = new WritableNativeArray();
@@ -77,8 +73,8 @@ public class Arguments {
}
/**
* This overload is like the above, but uses reflection to operate on any
* primitive or object type.
* This overload is like the above, but uses reflection to operate on any primitive or object
* type.
*/
public static <T> WritableNativeArray makeNativeArray(final Object objects) {
if (objects == null) {
@@ -86,15 +82,16 @@ public class Arguments {
}
// No explicit check for objects's type here. If it's not an array, the
// Array methods will throw IllegalArgumentException.
return makeNativeArray(new AbstractList() {
public int size() {
return Array.getLength(objects);
}
return makeNativeArray(
new AbstractList() {
public int size() {
return Array.getLength(objects);
}
public Object get(int index) {
return Array.get(objects, index);
}
});
public Object get(int index) {
return Array.get(objects, index);
}
});
}
private static void addEntry(WritableNativeMap nativeMap, String key, Object value) {
@@ -119,10 +116,9 @@ public class Arguments {
}
/**
* This method converts a Map into a NativeMap. Value types are supported as
* with makeNativeArray. The best way to think of this is a way to generate
* a Java representation of a json object, from Java types which have a
* natural representation in json.
* This method converts a Map into a NativeMap. Value types are supported as with makeNativeArray.
* The best way to think of this is a way to generate a Java representation of a json object, from
* Java types which have a natural representation in json.
*/
public static WritableNativeMap makeNativeMap(Map<String, Object> objects) {
WritableNativeMap nativeMap = new WritableNativeMap();
@@ -135,9 +131,7 @@ public class Arguments {
return nativeMap;
}
/**
* Like the above, but takes a Bundle instead of a Map.
*/
/** Like the above, but takes a Bundle instead of a Map. */
public static WritableNativeMap makeNativeMap(Bundle bundle) {
WritableNativeMap nativeMap = new WritableNativeMap();
if (bundle == null) {
@@ -149,16 +143,12 @@ public class Arguments {
return nativeMap;
}
/**
* This method should be used when you need to stub out creating NativeArrays in unit tests.
*/
/** This method should be used when you need to stub out creating NativeArrays in unit tests. */
public static WritableArray createArray() {
return new WritableNativeArray();
}
/**
* This method should be used when you need to stub out creating NativeMaps in unit tests.
*/
/** This method should be used when you need to stub out creating NativeMaps in unit tests. */
public static WritableMap createMap() {
return new WritableNativeMap();
}
@@ -198,7 +188,7 @@ public class Arguments {
* Convert an array to a {@link WritableArray}.
*
* @param array the array to convert. Supported types are: {@code String[]}, {@code Bundle[]},
* {@code int[]}, {@code float[]}, {@code double[]}, {@code boolean[]}.
* {@code int[]}, {@code float[]}, {@code double[]}, {@code boolean[]}.
* @return the converted {@link WritableArray}
* @throws IllegalArgumentException if the passed object is none of the above types
*/
@@ -237,10 +227,12 @@ public class Arguments {
/**
* Convert a {@link List} to a {@link WritableArray}.
*
* @param list the list to convert. Supported value types are: {@code null}, {@code String}, {@code Bundle},
* {@code List}, {@code Number}, {@code Boolean}, and all array types supported in {@link #fromArray(Object)}.
* @param list the list to convert. Supported value types are: {@code null}, {@code String},
* {@code Bundle}, {@code List}, {@code Number}, {@code Boolean}, and all array types
* supported in {@link #fromArray(Object)}.
* @return the converted {@link WritableArray}
* @throws IllegalArgumentException if one of the values from the passed list is none of the above types
* @throws IllegalArgumentException if one of the values from the passed list is none of the above
* types
*/
public static WritableArray fromList(List list) {
WritableArray catalystArray = createArray();
@@ -269,14 +261,15 @@ public class Arguments {
}
/**
* Convert a {@link Bundle} to a {@link WritableMap}. Supported key types in the bundle
* are:
* Convert a {@link Bundle} to a {@link WritableMap}. Supported key types in the bundle are:
*
* <p>
*
* <ul>
* <li>primitive types: int, float, double, boolean</li>
* <li>arrays supported by {@link #fromArray(Object)}</li>
* <li>lists supported by {@link #fromList(List)}</li>
* <li>{@link Bundle} objects that are recursively converted to maps</li>
* <li>primitive types: int, float, double, boolean
* <li>arrays supported by {@link #fromArray(Object)}
* <li>lists supported by {@link #fromList(List)}
* <li>{@link Bundle} objects that are recursively converted to maps
* </ul>
*
* @param bundle the {@link Bundle} to convert
@@ -362,8 +355,8 @@ public class Arguments {
}
/**
* Convert a {@link WritableMap} to a {@link Bundle}.
* Note: Each array is converted to an {@link ArrayList}.
* Convert a {@link WritableMap} to a {@link Bundle}. Note: Each array is converted to an {@link
* ArrayList}.
*
* @param readableMap the {@link WritableMap} to convert.
* @return the converted {@link Bundle}.
@@ -1,16 +1,15 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
/**
* Like {@link AssertionError} but extends RuntimeException so that it may be caught by a
* {@link NativeModuleCallExceptionHandler}. See that class for more details. Used in
* conjunction with {@link SoftAssertions}.
* Like {@link AssertionError} but extends RuntimeException so that it may be caught by a {@link
* NativeModuleCallExceptionHandler}. See that class for more details. Used in conjunction with
* {@link SoftAssertions}.
*/
public class AssertionException extends RuntimeException {
@@ -8,20 +8,16 @@ package com.facebook.react.bridge;
import android.app.Activity;
import android.content.Intent;
/**
* An empty implementation of {@link ActivityEventListener}
*/
/** An empty implementation of {@link ActivityEventListener} */
public class BaseActivityEventListener implements ActivityEventListener {
/**
* @deprecated use {@link #onActivityResult(Activity, int, int, Intent)} instead.
*/
/** @deprecated use {@link #onActivityResult(Activity, int, int, Intent)} instead. */
@Deprecated
public void onActivityResult(int requestCode, int resultCode, Intent data) { }
public void onActivityResult(int requestCode, int resultCode, Intent data) {}
@Override
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) { }
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {}
@Override
public void onNewIntent(Intent intent) { }
public void onNewIntent(Intent intent) {}
}
@@ -1,49 +1,44 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import javax.annotation.Nullable;
import java.util.Map;
import javax.annotation.Nullable;
/**
* Base class for Catalyst native modules whose implementations are written in Java. Default
* implementations for {@link #initialize} and {@link #onCatalystInstanceDestroy} are provided for
* convenience. Subclasses which override these don't need to call {@code super} in case of
* convenience. Subclasses which override these don't need to call {@code super} in case of
* overriding those methods as implementation of those methods is empty.
*
* BaseJavaModules can be linked to Fragments' lifecycle events, {@link CatalystInstance} creation
* and destruction, by being called on the appropriate method when a life cycle event occurs.
* <p>BaseJavaModules can be linked to Fragments' lifecycle events, {@link CatalystInstance}
* creation and destruction, by being called on the appropriate method when a life cycle event
* occurs.
*
* Native methods can be exposed to JS with {@link ReactMethod} annotation. Those methods may
* only use limited number of types for their arguments:
* 1/ primitives (boolean, int, float, double
* 2/ {@link String} mapped from JS string
* 3/ {@link ReadableArray} mapped from JS Array
* 4/ {@link ReadableMap} mapped from JS Object
* 5/ {@link Callback} mapped from js function and can be used only as a last parameter or in the
* case when it express success & error callback pair as two last arguments respectively.
* <p>Native methods can be exposed to JS with {@link ReactMethod} annotation. Those methods may
* only use limited number of types for their arguments: 1/ primitives (boolean, int, float, double
* 2/ {@link String} mapped from JS string 3/ {@link ReadableArray} mapped from JS Array 4/ {@link
* ReadableMap} mapped from JS Object 5/ {@link Callback} mapped from js function and can be used
* only as a last parameter or in the case when it express success & error callback pair as two last
* arguments respectively.
*
* All methods exposed as native to JS with {@link ReactMethod} annotation must return
* {@code void}.
* <p>All methods exposed as native to JS with {@link ReactMethod} annotation must return {@code
* void}.
*
* Please note that it is not allowed to have multiple methods annotated with {@link ReactMethod}
* <p>Please note that it is not allowed to have multiple methods annotated with {@link ReactMethod}
* with the same name.
*/
public abstract class BaseJavaModule implements NativeModule {
// taken from Libraries/Utilities/MessageQueue.js
static final public String METHOD_TYPE_ASYNC = "async";
static final public String METHOD_TYPE_PROMISE= "promise";
static final public String METHOD_TYPE_SYNC = "sync";
public static final String METHOD_TYPE_ASYNC = "async";
public static final String METHOD_TYPE_PROMISE = "promise";
public static final String METHOD_TYPE_SYNC = "sync";
/**
* @return a map of constants this module exports to JS. Supports JSON types.
*/
/** @return a map of constants this module exports to JS. Supports JSON types. */
public @Nullable Map<String, Object> getConstants() {
return null;
}
@@ -1,15 +1,14 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
/**
* Interface that represent javascript callback function which can be passed to the native module
* as a method parameter.
* Interface that represent javascript callback function which can be passed to the native module as
* a method parameter.
*/
public interface Callback {
@@ -19,5 +18,4 @@ public interface Callback {
* @param args arguments passed to javascript callback method via bridge
*/
public void invoke(Object... args);
}
@@ -1,15 +1,12 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
/**
* Implementation of javascript callback function that use Bridge to schedule method execution
*/
/** Implementation of javascript callback function that use Bridge to schedule method execution */
public final class CallbackImpl implements Callback {
private final JSInstance mJSInstance;
@@ -25,9 +22,10 @@ public final class CallbackImpl implements Callback {
@Override
public void invoke(Object... args) {
if (mInvoked) {
throw new RuntimeException("Illegal callback invocation from native "+
"module. This callback type only permits a single invocation from "+
"native code.");
throw new RuntimeException(
"Illegal callback invocation from native "
+ "module. This callback type only permits a single invocation from "
+ "native code.");
}
mJSInstance.invokeCallback(mCallbackId, Arguments.fromJavaArgs(args));
mInvoked = true;
@@ -1,25 +1,23 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.bridge.queue.ReactQueueConfiguration;
import com.facebook.react.common.annotations.VisibleForTesting;
import com.facebook.react.turbomodule.core.interfaces.JSCallInvokerHolder;
import com.facebook.react.turbomodule.core.interfaces.TurboModuleRegistry;
import java.util.Collection;
import java.util.List;
import javax.annotation.Nullable;
/**
* A higher level API on top of the asynchronous JSC bridge. This provides an
* environment allowing the invocation of JavaScript methods and lets a set of
* Java APIs be invokable from JavaScript as well.
* A higher level API on top of the asynchronous JSC bridge. This provides an environment allowing
* the invocation of JavaScript methods and lets a set of Java APIs be invokable from JavaScript as
* well.
*/
@DoNotStrip
public interface CatalystInstance
@@ -30,48 +28,50 @@ public interface CatalystInstance
boolean hasRunJSBundle();
/**
* Return the source URL of the JS Bundle that was run, or {@code null} if no JS
* bundle has been run yet.
* Return the source URL of the JS Bundle that was run, or {@code null} if no JS bundle has been
* run yet.
*/
@Nullable String getSourceURL();
@Nullable
String getSourceURL();
// This is called from java code, so it won't be stripped anyway, but proguard will rename it,
// which this prevents.
@Override @DoNotStrip
void invokeCallback(
int callbackID,
NativeArrayInterface arguments);
@Override
@DoNotStrip
void callFunction(
String module,
String method,
NativeArray arguments);
void invokeCallback(int callbackID, NativeArrayInterface arguments);
@DoNotStrip
void callFunction(String module, String method, NativeArray arguments);
/**
* Destroys this catalyst instance, waiting for any other threads in ReactQueueConfiguration
* (besides the UI thread) to finish running. Must be called from the UI thread so that we can
* fully shut down other threads.
*/
void destroy();
boolean isDestroyed();
/**
* Initialize all the native modules
*/
/** Initialize all the native modules */
@VisibleForTesting
void initialize();
ReactQueueConfiguration getReactQueueConfiguration();
<T extends JavaScriptModule> T getJSModule(Class<T> jsInterface);
<T extends NativeModule> boolean hasNativeModule(Class<T> nativeModuleInterface);
<T extends NativeModule> T getNativeModule(Class<T> nativeModuleInterface);
NativeModule getNativeModule(String moduleName);
JSIModule getJSIModule(JSIModuleType moduleType);
Collection<NativeModule> getNativeModules();
/**
* This method permits a CatalystInstance to extend the known
* Native modules. This provided registry contains only the new modules to load.
* This method permits a CatalystInstance to extend the known Native modules. This provided
* registry contains only the new modules to load.
*/
void extendNativeModules(NativeModuleRegistry modules);
@@ -84,8 +84,8 @@ public interface CatalystInstance
void addBridgeIdleDebugListener(NotThreadSafeBridgeIdleDebugListener listener);
/**
* Removes a NotThreadSafeBridgeIdleDebugListener previously added with
* {@link #addBridgeIdleDebugListener}
* Removes a NotThreadSafeBridgeIdleDebugListener previously added with {@link
* #addBridgeIdleDebugListener}
*/
void removeBridgeIdleDebugListener(NotThreadSafeBridgeIdleDebugListener listener);
@@ -107,16 +107,15 @@ public interface CatalystInstance
void addJSIModules(List<JSIModuleSpec> jsiModules);
/**
* Returns a hybrid object that contains a pointer to JSCallInvoker.
* Required for TurboModuleManager initialization.
* Returns a hybrid object that contains a pointer to JSCallInvoker. Required for
* TurboModuleManager initialization.
*/
JSCallInvokerHolder getJSCallInvokerHolder();
/**
* For the time being, we want code relying on the old infra to also
* work with TurboModules. Hence, we must provide the TurboModuleRegistry
* to CatalystInstance so that getNativeModule, hasNativeModule, and
* getNativeModules can also return TurboModules.
* For the time being, we want code relying on the old infra to also work with TurboModules.
* Hence, we must provide the TurboModuleRegistry to CatalystInstance so that getNativeModule,
* hasNativeModule, and getNativeModules can also return TurboModules.
*/
void setTurboModuleManager(JSIModule getter);
}
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE;
@@ -38,8 +37,8 @@ import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Nullable;
/**
* This provides an implementation of the public CatalystInstance instance. It is public because
* it is built by XReactInstanceManager which is in a different package.
* This provides an implementation of the public CatalystInstance instance. It is public because it
* is built by XReactInstanceManager which is in a different package.
*/
@DoNotStrip
public class CatalystInstanceImpl implements CatalystInstance {
@@ -67,8 +66,12 @@ public class CatalystInstanceImpl implements CatalystInstance {
}
public String toString() {
return mModule + "." + mMethod + "("
+ (mArguments == null ? "" : mArguments.toString()) + ")";
return mModule
+ "."
+ mMethod
+ "("
+ (mArguments == null ? "" : mArguments.toString())
+ ")";
}
}
@@ -100,7 +103,9 @@ public class CatalystInstanceImpl implements CatalystInstance {
// C++ parts
private final HybridData mHybridData;
private native static HybridData initHybrid();
private static native HybridData initHybrid();
public native JSCallInvokerHolderImpl getJSCallInvokerHolder();
private CatalystInstanceImpl(
@@ -114,9 +119,9 @@ public class CatalystInstanceImpl implements CatalystInstance {
mHybridData = initHybrid();
mReactQueueConfiguration = ReactQueueConfigurationImpl.create(
reactQueueConfigurationSpec,
new NativeExceptionHandler());
mReactQueueConfiguration =
ReactQueueConfigurationImpl.create(
reactQueueConfigurationSpec, new NativeExceptionHandler());
mBridgeIdleListeners = new CopyOnWriteArrayList<>();
mNativeModuleRegistry = nativeModuleRegistry;
mJSModuleRegistry = new JavaScriptModuleRegistry();
@@ -129,12 +134,12 @@ public class CatalystInstanceImpl implements CatalystInstance {
Log.d(ReactConstants.TAG, "Initializing React Xplat Bridge before initializeBridge");
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "initializeCxxBridge");
initializeBridge(
new BridgeCallback(this),
jsExecutor,
mReactQueueConfiguration.getJSQueueThread(),
mNativeModulesQueueThread,
mNativeModuleRegistry.getJavaModules(this),
mNativeModuleRegistry.getCxxModules());
new BridgeCallback(this),
jsExecutor,
mReactQueueConfiguration.getJSQueueThread(),
mNativeModulesQueueThread,
mNativeModuleRegistry.getJavaModules(this),
mNativeModuleRegistry.getCxxModules());
Log.d(ReactConstants.TAG, "Initializing React Xplat Bridge after initializeBridge");
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
@@ -177,24 +182,23 @@ public class CatalystInstanceImpl implements CatalystInstance {
}
/**
* This method and the native below permits a CatalystInstance to extend the known
* Native modules. This registry contains only the new modules to load. The
* registry {@code mNativeModuleRegistry} updates internally to contain all the new modules, and generates
* the new registry for extracting just the new collections.
* This method and the native below permits a CatalystInstance to extend the known Native modules.
* This registry contains only the new modules to load. The registry {@code mNativeModuleRegistry}
* updates internally to contain all the new modules, and generates the new registry for
* extracting just the new collections.
*/
@Override
public void extendNativeModules(NativeModuleRegistry modules) {
//Extend the Java-visible registry of modules
// Extend the Java-visible registry of modules
mNativeModuleRegistry.registerModules(modules);
Collection<JavaModuleWrapper> javaModules = modules.getJavaModules(this);
Collection<ModuleHolder> cxxModules = modules.getCxxModules();
//Extend the Cxx-visible registry of modules wrapped in appropriate interfaces
// Extend the Cxx-visible registry of modules wrapped in appropriate interfaces
jniExtendNativeModules(javaModules, cxxModules);
}
private native void jniExtendNativeModules(
Collection<JavaModuleWrapper> javaModules,
Collection<ModuleHolder> cxxModules);
Collection<JavaModuleWrapper> javaModules, Collection<ModuleHolder> cxxModules);
private native void initializeBridge(
ReactCallback callback,
@@ -216,7 +220,8 @@ public class CatalystInstanceImpl implements CatalystInstance {
}
@Override
public void loadScriptFromAssets(AssetManager assetManager, String assetURL, boolean loadSynchronously) {
public void loadScriptFromAssets(
AssetManager assetManager, String assetURL, boolean loadSynchronously) {
mSourceURL = assetURL;
jniLoadScriptFromAssets(assetManager, assetURL, loadSynchronously);
}
@@ -229,18 +234,23 @@ public class CatalystInstanceImpl implements CatalystInstance {
@Override
public void loadScriptFromDeltaBundle(
String sourceURL,
NativeDeltaClient deltaClient,
boolean loadSynchronously) {
String sourceURL, NativeDeltaClient deltaClient, boolean loadSynchronously) {
mSourceURL = sourceURL;
jniLoadScriptFromDeltaBundle(sourceURL, deltaClient, loadSynchronously);
}
private native void jniSetSourceURL(String sourceURL);
private native void jniRegisterSegment(int segmentId, String path);
private native void jniLoadScriptFromAssets(AssetManager assetManager, String assetURL, boolean loadSynchronously);
private native void jniLoadScriptFromFile(String fileName, String sourceURL, boolean loadSynchronously);
private native void jniLoadScriptFromDeltaBundle(String sourceURL, NativeDeltaClient deltaClient, boolean loadSynchronously);
private native void jniLoadScriptFromAssets(
AssetManager assetManager, String assetURL, boolean loadSynchronously);
private native void jniLoadScriptFromFile(
String fileName, String sourceURL, boolean loadSynchronously);
private native void jniLoadScriptFromDeltaBundle(
String sourceURL, NativeDeltaClient deltaClient, boolean loadSynchronously);
@Override
public void runJSBundle() {
@@ -279,16 +289,10 @@ public class CatalystInstanceImpl implements CatalystInstance {
return mSourceURL;
}
private native void jniCallJSFunction(
String module,
String method,
NativeArray arguments);
private native void jniCallJSFunction(String module, String method, NativeArray arguments);
@Override
public void callFunction(
final String module,
final String method,
final NativeArray arguments) {
public void callFunction(final String module, final String method, final NativeArray arguments) {
callFunction(new PendingJSCall(module, method, arguments));
}
@@ -385,29 +389,25 @@ public class CatalystInstanceImpl implements CatalystInstance {
return mDestroyed;
}
/**
* Initialize all the native modules
*/
/** Initialize all the native modules */
@VisibleForTesting
@Override
public void initialize() {
Log.d(ReactConstants.TAG, "CatalystInstanceImpl.initialize()");
Assertions.assertCondition(
!mInitialized,
"This catalyst instance has already been initialized");
!mInitialized, "This catalyst instance has already been initialized");
// We assume that the instance manager blocks on running the JS bundle. If
// that changes, then we need to set mAcceptCalls just after posting the
// task that will run the js bundle.
Assertions.assertCondition(
mAcceptCalls,
"RunJSBundle hasn't completed.");
Assertions.assertCondition(mAcceptCalls, "RunJSBundle hasn't completed.");
mInitialized = true;
mNativeModulesQueueThread.runOnQueue(new Runnable() {
@Override
public void run() {
mNativeModuleRegistry.notifyJSInstanceInitialized();
}
});
mNativeModulesQueueThread.runOnQueue(
new Runnable() {
@Override
public void run() {
mNativeModuleRegistry.notifyJSInstanceInitialized();
}
});
}
@Override
@@ -423,7 +423,9 @@ public class CatalystInstanceImpl implements CatalystInstance {
@Override
public <T extends NativeModule> boolean hasNativeModule(Class<T> nativeModuleInterface) {
String moduleName = getNameFromAnnotation(nativeModuleInterface);
return mTurboModuleRegistry != null && mTurboModuleRegistry.hasModule(moduleName) ? true : mNativeModuleRegistry.hasModule(moduleName);
return mTurboModuleRegistry != null && mTurboModuleRegistry.hasModule(moduleName)
? true
: mNativeModuleRegistry.hasModule(moduleName);
}
@Override
@@ -437,17 +439,18 @@ public class CatalystInstanceImpl implements CatalystInstance {
TurboModule turboModule = mTurboModuleRegistry.getModule(moduleName);
if (turboModule != null) {
return (NativeModule)turboModule;
return (NativeModule) turboModule;
}
}
return mNativeModuleRegistry.getModule(moduleName);
}
private <T extends NativeModule> String getNameFromAnnotation(Class<T> nativeModuleInterface){
private <T extends NativeModule> String getNameFromAnnotation(Class<T> nativeModuleInterface) {
ReactModule annotation = nativeModuleInterface.getAnnotation(ReactModule.class);
if (annotation == null) {
throw new IllegalArgumentException("Could not find @ReactModule annotation in " + nativeModuleInterface.getCanonicalName());
throw new IllegalArgumentException(
"Could not find @ReactModule annotation in " + nativeModuleInterface.getCanonicalName());
}
return annotation.name();
}
@@ -489,8 +492,8 @@ public class CatalystInstanceImpl implements CatalystInstance {
}
/**
* Removes a NotThreadSafeBridgeIdleDebugListener previously added with
* {@link #addBridgeIdleDebugListener}
* Removes a NotThreadSafeBridgeIdleDebugListener previously added with {@link
* #addBridgeIdleDebugListener}
*/
@Override
public void removeBridgeIdleDebugListener(NotThreadSafeBridgeIdleDebugListener listener) {
@@ -521,56 +524,56 @@ public class CatalystInstanceImpl implements CatalystInstance {
int oldPendingCalls = mPendingJSCalls.getAndIncrement();
boolean wasIdle = oldPendingCalls == 0;
Systrace.traceCounter(
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
mJsPendingCallsTitleForTrace,
oldPendingCalls + 1);
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, mJsPendingCallsTitleForTrace, oldPendingCalls + 1);
if (wasIdle && !mBridgeIdleListeners.isEmpty()) {
mNativeModulesQueueThread.runOnQueue(new Runnable() {
@Override
public void run() {
for (NotThreadSafeBridgeIdleDebugListener listener : mBridgeIdleListeners) {
listener.onTransitionToBridgeBusy();
}
}
});
mNativeModulesQueueThread.runOnQueue(
new Runnable() {
@Override
public void run() {
for (NotThreadSafeBridgeIdleDebugListener listener : mBridgeIdleListeners) {
listener.onTransitionToBridgeBusy();
}
}
});
}
}
public void setTurboModuleManager(JSIModule getter) {
mTurboModuleRegistry = (TurboModuleRegistry)getter;
mTurboModuleRegistry = (TurboModuleRegistry) getter;
}
private void decrementPendingJSCalls() {
int newPendingCalls = mPendingJSCalls.decrementAndGet();
// TODO(9604406): handle case of web workers injecting messages to main thread
//Assertions.assertCondition(newPendingCalls >= 0);
// Assertions.assertCondition(newPendingCalls >= 0);
boolean isNowIdle = newPendingCalls == 0;
Systrace.traceCounter(
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
mJsPendingCallsTitleForTrace,
newPendingCalls);
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, mJsPendingCallsTitleForTrace, newPendingCalls);
if (isNowIdle && !mBridgeIdleListeners.isEmpty()) {
mNativeModulesQueueThread.runOnQueue(new Runnable() {
@Override
public void run() {
for (NotThreadSafeBridgeIdleDebugListener listener : mBridgeIdleListeners) {
listener.onTransitionToBridgeIdle();
}
}
});
mNativeModulesQueueThread.runOnQueue(
new Runnable() {
@Override
public void run() {
for (NotThreadSafeBridgeIdleDebugListener listener : mBridgeIdleListeners) {
listener.onTransitionToBridgeIdle();
}
}
});
}
}
private void onNativeException(Exception e) {
mNativeModuleCallExceptionHandler.handleException(e);
mReactQueueConfiguration.getUIQueueThread().runOnQueue(
new Runnable() {
@Override
public void run() {
destroy();
}
});
mReactQueueConfiguration
.getUIQueueThread()
.runOnQueue(
new Runnable() {
@Override
public void run() {
destroy();
}
});
}
private class NativeExceptionHandler implements QueueThreadExceptionHandler {
@@ -619,7 +622,6 @@ public class CatalystInstanceImpl implements CatalystInstance {
private @Nullable JavaScriptExecutor mJSExecutor;
private @Nullable NativeModuleCallExceptionHandler mNativeModuleCallExceptionHandler;
public Builder setReactQueueConfigurationSpec(
ReactQueueConfigurationSpec ReactQueueConfigurationSpec) {
mReactQueueConfigurationSpec = ReactQueueConfigurationSpec;
@@ -641,8 +643,7 @@ public class CatalystInstanceImpl implements CatalystInstance {
return this;
}
public Builder setNativeModuleCallExceptionHandler(
NativeModuleCallExceptionHandler handler) {
public Builder setNativeModuleCallExceptionHandler(NativeModuleCallExceptionHandler handler) {
mNativeModuleCallExceptionHandler = handler;
return this;
}
@@ -1,17 +1,15 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import android.content.Context;
/**
* Base class for React native modules that require access to an Android
* {@link Context} instance.
* Base class for React native modules that require access to an Android {@link Context} instance.
*/
public abstract class ContextBaseJavaModule extends BaseJavaModule {
@@ -21,9 +19,7 @@ public abstract class ContextBaseJavaModule extends BaseJavaModule {
mContext = context;
}
/**
* Subclasses can use this method to access Android context passed as a constructor
*/
/** Subclasses can use this method to access Android context passed as a constructor */
protected final Context getContext() {
return mContext;
}
@@ -5,20 +5,15 @@
package com.facebook.react.bridge;
import com.facebook.jni.HybridData;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.NativeArray;
import static com.facebook.react.bridge.Arguments.*;
/**
* Callback impl that calls directly into the cxx bridge. Created from C++.
*/
import com.facebook.jni.HybridData;
import com.facebook.proguard.annotations.DoNotStrip;
/** Callback impl that calls directly into the cxx bridge. Created from C++. */
@DoNotStrip
public class CxxCallbackImpl implements Callback {
@DoNotStrip
private final HybridData mHybridData;
@DoNotStrip private final HybridData mHybridData;
@DoNotStrip
private CxxCallbackImpl(HybridData hybridData) {
@@ -9,12 +9,9 @@ import com.facebook.jni.HybridData;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.soloader.SoLoader;
/**
* This does nothing interesting, except avoid breaking existing code.
*/
/** This does nothing interesting, except avoid breaking existing code. */
@DoNotStrip
public class CxxModuleWrapper extends CxxModuleWrapperBase
{
public class CxxModuleWrapper extends CxxModuleWrapperBase {
protected CxxModuleWrapper(HybridData hd) {
super(hd);
}
@@ -11,18 +11,16 @@ import com.facebook.proguard.annotations.DoNotStrip;
/**
* A Java Object which represents a cross-platform C++ module
*
* This module implements the NativeModule interface but will never be invoked from Java,
* instead the underlying Cxx module will be extracted by the bridge and called directly.
* <p>This module implements the NativeModule interface but will never be invoked from Java, instead
* the underlying Cxx module will be extracted by the bridge and called directly.
*/
@DoNotStrip
public class CxxModuleWrapperBase implements NativeModule
{
public class CxxModuleWrapperBase implements NativeModule {
static {
ReactBridge.staticInit();
}
@DoNotStrip
private HybridData mHybridData;
@DoNotStrip private HybridData mHybridData;
@Override
public native String getName();
@@ -1,15 +1,12 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
/**
* Crashy crashy exception handler.
*/
/** Crashy crashy exception handler. */
public class DefaultNativeModuleCallExceptionHandler implements NativeModuleCallExceptionHandler {
@Override
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
/**
@@ -13,12 +12,20 @@ package com.facebook.react.bridge;
*/
public interface Dynamic {
boolean isNull();
boolean asBoolean();
double asDouble();
int asInt();
String asString();
ReadableArray asArray();
ReadableMap asMap();
ReadableType getType();
void recycle();
}
@@ -1,19 +1,15 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import androidx.core.util.Pools;
import javax.annotation.Nullable;
import androidx.core.util.Pools;
/**
* Implementation of Dynamic wrapping a ReadableArray.
*/
/** Implementation of Dynamic wrapping a ReadableArray. */
public class DynamicFromArray implements Dynamic {
private static final Pools.SimplePool<DynamicFromArray> sPool = new Pools.SimplePool<>(10);
@@ -1,26 +1,23 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import androidx.core.util.Pools.SimplePool;
import javax.annotation.Nullable;
import androidx.core.util.Pools.SimplePool;
/**
* Implementation of Dynamic wrapping a ReadableMap.
*/
/** Implementation of Dynamic wrapping a ReadableMap. */
public class DynamicFromMap implements Dynamic {
private static final ThreadLocal<SimplePool<DynamicFromMap>> sPool = new ThreadLocal<SimplePool<DynamicFromMap>>() {
@Override
protected SimplePool<DynamicFromMap> initialValue() {
return new SimplePool<>(10);
}
};
private static final ThreadLocal<SimplePool<DynamicFromMap>> sPool =
new ThreadLocal<SimplePool<DynamicFromMap>>() {
@Override
protected SimplePool<DynamicFromMap> initialValue() {
return new SimplePool<>(10);
}
};
private @Nullable ReadableMap mMap;
private @Nullable String mName;
@@ -1,19 +1,16 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import com.facebook.common.logging.FLog;
import com.facebook.react.common.ReactConstants;
import javax.annotation.Nullable;
/**
* Implementation of Dynamic wrapping a ReadableArray.
*/
/** Implementation of Dynamic wrapping a ReadableArray. */
public class DynamicFromObject implements Dynamic {
private @Nullable Object mObject;
@@ -33,33 +30,33 @@ public class DynamicFromObject implements Dynamic {
@Override
public boolean asBoolean() {
return (boolean)mObject;
return (boolean) mObject;
}
@Override
public double asDouble() {
return (double)mObject;
return (double) mObject;
}
@Override
public int asInt() {
// Numbers from JS are always Doubles
return ((Double)mObject).intValue();
return ((Double) mObject).intValue();
}
@Override
public String asString() {
return (String)mObject;
return (String) mObject;
}
@Override
public ReadableArray asArray() {
return (ReadableArray)mObject;
return (ReadableArray) mObject;
}
@Override
public ReadableMap asMap() {
return (ReadableMap)mObject;
return (ReadableMap) mObject;
}
@Override
@@ -1,25 +1,23 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import com.facebook.common.logging.FLog;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.Stack;
import com.facebook.common.logging.FLog;
/**
* FallbackJSBundleLoader
*
* An implementation of {@link JSBundleLoader} that will try to load from
* multiple sources, falling back from one source to the next at load time
* when an exception is thrown for a recoverable error.
* <p>An implementation of {@link JSBundleLoader} that will try to load from multiple sources,
* falling back from one source to the next at load time when an exception is thrown for a
* recoverable error.
*/
public final class FallbackJSBundleLoader extends JSBundleLoader {
@@ -32,10 +30,7 @@ public final class FallbackJSBundleLoader extends JSBundleLoader {
// Reasons why we fell-back on previous loaders, in order of occurrence.
private final ArrayList<Exception> mRecoveredErrors = new ArrayList<>();
/**
* @param loaders Loaders for the sources to try, in descending order of
* preference.
*/
/** @param loaders Loaders for the sources to try, in descending order of preference. */
public FallbackJSBundleLoader(List<JSBundleLoader> loaders) {
mLoaders = new Stack();
ListIterator<JSBundleLoader> it = loaders.listIterator(loaders.size());
@@ -45,9 +40,9 @@ public final class FallbackJSBundleLoader extends JSBundleLoader {
}
/**
* This loader delegates to (and so behaves like) the currently preferred
* loader. If that loader fails in a recoverable way and we fall back from it,
* it is replaced by the next most preferred loader.
* This loader delegates to (and so behaves like) the currently preferred loader. If that loader
* fails in a recoverable way and we fall back from it, it is replaced by the next most preferred
* loader.
*/
@Override
public String loadScript(JSBundleLoaderDelegate delegate) {
@@ -71,8 +66,7 @@ public final class FallbackJSBundleLoader extends JSBundleLoader {
return mLoaders.peek();
}
RuntimeException fallbackException =
new RuntimeException("No fallback options available");
RuntimeException fallbackException = new RuntimeException("No fallback options available");
// Invariant: tail.getCause() == null
Throwable tail = fallbackException;
@@ -1,24 +1,22 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import android.os.AsyncTask;
/**
* Abstract base for a AsyncTask that should have any RuntimeExceptions it throws
* handled by the {@link com.facebook.react.bridge.NativeModuleCallExceptionHandler} registered if
* the app is in dev mode.
* Abstract base for a AsyncTask that should have any RuntimeExceptions it throws handled by the
* {@link com.facebook.react.bridge.NativeModuleCallExceptionHandler} registered if the app is in
* dev mode.
*
* This class doesn't allow doInBackground to return a results. If you need this
* use GuardedResultAsyncTask instead.
* <p>This class doesn't allow doInBackground to return a results. If you need this use
* GuardedResultAsyncTask instead.
*/
public abstract class GuardedAsyncTask<Params, Progress>
extends AsyncTask<Params, Progress, Void> {
public abstract class GuardedAsyncTask<Params, Progress> extends AsyncTask<Params, Progress, Void> {
private final ReactContext mReactContext;
@@ -12,8 +12,7 @@ import android.os.AsyncTask;
* throws handled by the {@link com.facebook.react.bridge.NativeModuleCallExceptionHandler}
* registered if the app is in dev mode.
*/
public abstract class GuardedResultAsyncTask<Result>
extends AsyncTask<Void, Void, Result> {
public abstract class GuardedResultAsyncTask<Result> extends AsyncTask<Void, Void, Result> {
private final ReactContext mReactContext;
@@ -41,6 +40,6 @@ public abstract class GuardedResultAsyncTask<Result>
}
protected abstract Result doInBackgroundGuarded();
protected abstract void onPostExecuteGuarded(Result result);
protected abstract void onPostExecuteGuarded(Result result);
}
@@ -6,9 +6,9 @@
package com.facebook.react.bridge;
/**
* Abstract base for a Runnable that should have any RuntimeExceptions it throws
* handled by the {@link com.facebook.react.bridge.NativeModuleCallExceptionHandler} registered if
* the app is in dev mode.
* Abstract base for a Runnable that should have any RuntimeExceptions it throws handled by the
* {@link com.facebook.react.bridge.NativeModuleCallExceptionHandler} registered if the app is in
* dev mode.
*/
public abstract class GuardedRunnable implements Runnable {
@@ -5,14 +5,13 @@
package com.facebook.react.bridge;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import com.facebook.common.logging.FLog;
import com.facebook.jni.HybridData;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.common.ReactConstants;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@DoNotStrip
public class Inspector {
@@ -70,10 +69,7 @@ public class Inspector {
@Override
public String toString() {
return "Page{" +
"mId=" + mId +
", mTitle='" + mTitle + '\'' +
'}';
return "Page{" + "mId=" + mId + ", mTitle='" + mTitle + '\'' + '}';
}
@DoNotStrip
@@ -88,6 +84,7 @@ public class Inspector {
public interface RemoteConnection {
@DoNotStrip
void onMessage(String message);
@DoNotStrip
void onDisconnect();
}
@@ -97,6 +94,7 @@ public class Inspector {
private final HybridData mHybridData;
public native void sendMessage(String message);
public native void disconnect();
private LocalConnection(HybridData hybridData) {
@@ -1,17 +1,16 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import com.facebook.proguard.annotations.DoNotStrip;
/**
* Exception thrown by {@link ReadableMapKeySetIterator#nextKey()} when the iterator tries
* to iterate over elements after the end of the key set.
* Exception thrown by {@link ReadableMapKeySetIterator#nextKey()} when the iterator tries to
* iterate over elements after the end of the key set.
*/
@DoNotStrip
public class InvalidIteratorException extends RuntimeException {
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import javax.annotation.Nullable;
@@ -13,19 +12,18 @@ import javax.annotation.Nullable;
* A special RuntimeException that should be thrown by native code if it has reached an exceptional
* state due to a, or a sequence of, bad commands.
*
* A good rule of thumb for whether a native Exception should extend this interface is 1) Can a
* <p>A good rule of thumb for whether a native Exception should extend this interface is 1) Can a
* developer make a change or correction in JS to keep this Exception from being thrown? 2) Is the
* app outside of this catalyst instance still in a good state to allow reloading and restarting
* this catalyst instance?
*
* Examples where this class is appropriate to throw:
* - JS tries to update a view with a tag that hasn't been created yet
* - JS tries to show a static image that isn't in resources
* - JS tries to use an unsupported view class
* <p>Examples where this class is appropriate to throw: - JS tries to update a view with a tag that
* hasn't been created yet - JS tries to show a static image that isn't in resources - JS tries to
* use an unsupported view class
*
* Examples where this class **isn't** appropriate to throw:
* - Failed to write to localStorage because disk is full
* - Assertions about internal state (e.g. that child.getParent().indexOf(child) != -1)
* <p>Examples where this class **isn't** appropriate to throw: - Failed to write to localStorage
* because disk is full - Assertions about internal state (e.g. that
* child.getParent().indexOf(child) != -1)
*/
public class JSApplicationCausedNativeException extends RuntimeException {
@@ -34,8 +32,7 @@ public class JSApplicationCausedNativeException extends RuntimeException {
}
public JSApplicationCausedNativeException(
@Nullable String detailMessage,
@Nullable Throwable throwable) {
@Nullable String detailMessage, @Nullable Throwable throwable) {
super(detailMessage, throwable);
}
}
@@ -1,15 +1,12 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
/**
* An illegal argument Exception caused by an argument passed from JS.
*/
/** An illegal argument Exception caused by an argument passed from JS. */
public class JSApplicationIllegalArgumentException extends JSApplicationCausedNativeException {
public JSApplicationIllegalArgumentException(String detailMessage) {
@@ -1,18 +1,17 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import android.content.Context;
import com.facebook.react.common.DebugServerException;
/**
* A class that stores JS bundle information and allows a {@link JSBundleLoaderDelegate}
* (e.g. {@link CatalystInstance}) to load a correct bundle through {@link ReactBridge}.
* A class that stores JS bundle information and allows a {@link JSBundleLoaderDelegate} (e.g.
* {@link CatalystInstance}) to load a correct bundle through {@link ReactBridge}.
*/
public abstract class JSBundleLoader {
@@ -22,9 +21,7 @@ public abstract class JSBundleLoader {
* strings from java to native memory.
*/
public static JSBundleLoader createAssetLoader(
final Context context,
final String assetUrl,
final boolean loadSynchronously) {
final Context context, final String assetUrl, final boolean loadSynchronously) {
return new JSBundleLoader() {
@Override
public String loadScript(JSBundleLoaderDelegate delegate) {
@@ -43,9 +40,7 @@ public abstract class JSBundleLoader {
}
public static JSBundleLoader createFileLoader(
final String fileName,
final String assetUrl,
final boolean loadSynchronously) {
final String fileName, final String assetUrl, final boolean loadSynchronously) {
return new JSBundleLoader() {
@Override
public String loadScript(JSBundleLoaderDelegate delegate) {
@@ -63,8 +58,7 @@ public abstract class JSBundleLoader {
* work correctly and allows for source maps to correctly symbolize those.
*/
public static JSBundleLoader createCachedBundleFromNetworkLoader(
final String sourceURL,
final String cachedFileLocation) {
final String sourceURL, final String cachedFileLocation) {
return new JSBundleLoader() {
@Override
public String loadScript(JSBundleLoaderDelegate delegate) {
@@ -82,11 +76,11 @@ public abstract class JSBundleLoader {
* This loader is used to load delta bundles from the dev server. We pass each delta message to
* the loader and process it in C++. Passing it as a string leads to inefficiencies due to memory
* copies, which will have to be addressed in a follow-up.
*
* @param nativeDeltaClient
*/
public static JSBundleLoader createDeltaFromNetworkLoader(
final String sourceURL,
final NativeDeltaClient nativeDeltaClient) {
final String sourceURL, final NativeDeltaClient nativeDeltaClient) {
return new JSBundleLoader() {
@Override
public String loadScript(JSBundleLoaderDelegate delegate) {
@@ -105,8 +99,7 @@ public abstract class JSBundleLoader {
* the bundle from device as remote executor will have to do it anyway.
*/
public static JSBundleLoader createRemoteDebuggerBundleLoader(
final String proxySourceURL,
final String realSourceURL) {
final String proxySourceURL, final String realSourceURL) {
return new JSBundleLoader() {
@Override
public String loadScript(JSBundleLoaderDelegate delegate) {
@@ -1,22 +1,21 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import android.content.Context;
import android.content.res.AssetManager;
/**
* An interface for classes that initialize JavaScript using {@link JSBundleLoader}
*/
/** An interface for classes that initialize JavaScript using {@link JSBundleLoader} */
public interface JSBundleLoaderDelegate {
/**
* Load a JS bundle from Android assets. See {@link JSBundleLoader#createAssetLoader(Context, String, boolean)}
* Load a JS bundle from Android assets. See {@link JSBundleLoader#createAssetLoader(Context,
* String, boolean)}
*
* @param assetManager
* @param assetURL
* @param loadSynchronously
@@ -24,8 +23,9 @@ public interface JSBundleLoaderDelegate {
void loadScriptFromAssets(AssetManager assetManager, String assetURL, boolean loadSynchronously);
/**
* Load a JS bundle from the filesystem.
* See {@link JSBundleLoader#createFileLoader(String)} and {@link JSBundleLoader#createCachedBundleFromNetworkLoader(String, String)}
* Load a JS bundle from the filesystem. See {@link JSBundleLoader#createFileLoader(String)} and
* {@link JSBundleLoader#createCachedBundleFromNetworkLoader(String, String)}
*
* @param fileName
* @param sourceURL
* @param loadSynchronously
@@ -33,26 +33,23 @@ public interface JSBundleLoaderDelegate {
void loadScriptFromFile(String fileName, String sourceURL, boolean loadSynchronously);
/**
* Load a delta bundle from Metro.
* See {@link JSBundleLoader#createDeltaFromNetworkLoader(String, NativeDeltaClient)}
* Load a delta bundle from Metro. See {@link JSBundleLoader#createDeltaFromNetworkLoader(String,
* NativeDeltaClient)}
*
* @param sourceURL
* @param deltaClient
* @param loadSynchronously
*/
void loadScriptFromDeltaBundle(
String sourceURL,
NativeDeltaClient deltaClient,
boolean loadSynchronously);
String sourceURL, NativeDeltaClient deltaClient, boolean loadSynchronously);
/**
* This API is used in situations where the JS bundle is being executed not on
* the device, but on a host machine. In that case, we must provide two source
* URLs for the JS bundle: One to be used on the device, and one to be used on
* the remote debugging machine.
* This API is used in situations where the JS bundle is being executed not on the device, but on
* a host machine. In that case, we must provide two source URLs for the JS bundle: One to be used
* on the device, and one to be used on the remote debugging machine.
*
* @param deviceURL A source URL that is accessible from this device.
* @param remoteURL A source URL that is accessible from the remote machine
* executing the JS.
* @param remoteURL A source URL that is accessible from the remote machine executing the JS.
*/
void setSourceURLs(String deviceURL, String remoteURL);
}
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import com.facebook.jni.HybridData;
@@ -25,6 +24,5 @@ import com.facebook.proguard.annotations.DoNotStrip;
return "JSCJavaScriptExecutor";
}
private native static HybridData initHybrid(ReadableNativeMap jscConfig);
private static native HybridData initHybrid(ReadableNativeMap jscConfig);
}
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
public class JSCJavaScriptExecutorFactory implements JavaScriptExecutorFactory {
@@ -1,26 +1,21 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
/**
* Marker interface used to represent a JSI Module.
*/
/** Marker interface used to represent a JSI Module. */
public interface JSIModule {
/**
* This is called at the end of {@link CatalystApplicationFragment#createCatalystInstance()}
* after the CatalystInstance has been created, in order to initialize NativeModules that require
* the CatalystInstance or JS modules.
* This is called at the end of {@link CatalystApplicationFragment#createCatalystInstance()} after
* the CatalystInstance has been created, in order to initialize NativeModules that require the
* CatalystInstance or JS modules.
*/
void initialize();
/**
* Called before {CatalystInstance#onHostDestroy}
*/
/** Called before {CatalystInstance#onHostDestroy} */
void onCatalystInstanceDestroy();
}
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
public class JSIModuleHolder {
@@ -1,22 +1,17 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import java.util.List;
/**
* Interface used to initialize JSI Modules into the JSI Bridge.
*/
/** Interface used to initialize JSI Modules into the JSI Bridge. */
public interface JSIModulePackage {
/**
* @return a {@link List< JSIModuleSpec >} that contain the list of JSI Modules.
*/
List<JSIModuleSpec> getJSIModules(ReactApplicationContext reactApplicationContext, JavaScriptContextHolder jsContext);
/** @return a {@link List< JSIModuleSpec >} that contain the list of JSI Modules. */
List<JSIModuleSpec> getJSIModules(
ReactApplicationContext reactApplicationContext, JavaScriptContextHolder jsContext);
}
@@ -1,14 +1,12 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
public interface JSIModuleProvider<T extends JSIModule> {
T get();
}
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import com.facebook.infer.annotation.Assertions;
@@ -16,7 +15,7 @@ public class JSIModuleRegistry {
private final Map<JSIModuleType, JSIModuleHolder> mModules = new HashMap<>();
public JSIModuleRegistry() { }
public JSIModuleRegistry() {}
public JSIModule getModule(JSIModuleType moduleType) {
JSIModuleHolder jsiModuleHolder = mModules.get(moduleType);
@@ -1,19 +1,15 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
/**
* Holder class used to register {@link JSIModule} into JSI Bridge.
*/
/** Holder class used to register {@link JSIModule} into JSI Bridge. */
public interface JSIModuleSpec<T extends JSIModule> {
JSIModuleType getJSIModuleType();
JSIModuleProvider<T> getJSIModuleProvider();
}
@@ -1,15 +1,14 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
/**
* A list of support JSIModules. These are usually core infra pieces, so there
* should be an explicit list.
* A list of support JSIModules. These are usually core infra pieces, so there should be an explicit
* list.
*/
public enum JSIModuleType {
TurboModuleManager,
@@ -1,21 +1,17 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
/**
* This interface includes the methods needed to use a running JS
* instance, without specifying any of the bridge-specific
* initialization or lifecycle management.
* This interface includes the methods needed to use a running JS instance, without specifying any
* of the bridge-specific initialization or lifecycle management.
*/
public interface JSInstance {
void invokeCallback(
int callbackID,
NativeArrayInterface arguments);
void invokeCallback(int callbackID, NativeArrayInterface arguments);
// TODO if this interface survives refactoring, think about adding
// callFunction.
}
@@ -1,18 +1,17 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import com.facebook.proguard.annotations.DoNotStrip;
/**
* This is class represents java version of native js executor interface. When set through
* {@link ProxyJavaScriptExecutor} as a {@link CatalystInstance} executor, native code will
* delegate js calls to the given implementation of this interface.
* This is class represents java version of native js executor interface. When set through {@link
* ProxyJavaScriptExecutor} as a {@link CatalystInstance} executor, native code will delegate js
* calls to the given implementation of this interface.
*/
@DoNotStrip
public interface JavaJSExecutor {
@@ -27,13 +26,14 @@ public interface JavaJSExecutor {
}
/**
* Close this executor and cleanup any resources that it was using. No further calls are
* expected after this.
* Close this executor and cleanup any resources that it was using. No further calls are expected
* after this.
*/
void close();
/**
* Load javascript into the js context
*
* @param sourceURL url or file location from which script content was loaded
*/
@DoNotStrip
@@ -41,13 +41,13 @@ public interface JavaJSExecutor {
/**
* Execute javascript method within js context
*
* @param methodName name of the method to be executed
* @param jsonArgsArray json encoded array of arguments provided for the method call
* @return json encoded value returned from the method call
*/
@DoNotStrip
String executeJSCall(String methodName, String jsonArgsArray)
throws ProxyExecutorException;
String executeJSCall(String methodName, String jsonArgsArray) throws ProxyExecutorException;
@DoNotStrip
void setGlobalVariable(String propertyName, String jsonEncodedValue);
@@ -1,10 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import static com.facebook.infer.annotation.Assertions.assertNotNull;
@@ -20,118 +19,118 @@ import javax.annotation.Nullable;
public class JavaMethodWrapper implements NativeModule.NativeMethod {
private static abstract class ArgumentExtractor<T> {
private abstract static class ArgumentExtractor<T> {
public int getJSArgumentsNeeded() {
return 1;
}
public abstract @Nullable T extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex);
JSInstance jsInstance, ReadableArray jsArguments, int atIndex);
}
static final private ArgumentExtractor<Boolean> ARGUMENT_EXTRACTOR_BOOLEAN =
new ArgumentExtractor<Boolean>() {
@Override
public Boolean extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
return jsArguments.getBoolean(atIndex);
}
};
static final private ArgumentExtractor<Double> ARGUMENT_EXTRACTOR_DOUBLE =
new ArgumentExtractor<Double>() {
@Override
public Double extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
return jsArguments.getDouble(atIndex);
}
};
static final private ArgumentExtractor<Float> ARGUMENT_EXTRACTOR_FLOAT =
new ArgumentExtractor<Float>() {
@Override
public Float extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
return (float) jsArguments.getDouble(atIndex);
}
};
static final private ArgumentExtractor<Integer> ARGUMENT_EXTRACTOR_INTEGER =
new ArgumentExtractor<Integer>() {
@Override
public Integer extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
return (int) jsArguments.getDouble(atIndex);
}
};
static final private ArgumentExtractor<String> ARGUMENT_EXTRACTOR_STRING =
new ArgumentExtractor<String>() {
@Override
public String extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
return jsArguments.getString(atIndex);
}
};
static final private ArgumentExtractor<ReadableArray> ARGUMENT_EXTRACTOR_ARRAY =
new ArgumentExtractor<ReadableArray>() {
@Override
public ReadableArray extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
return jsArguments.getArray(atIndex);
}
};
static final private ArgumentExtractor<Dynamic> ARGUMENT_EXTRACTOR_DYNAMIC =
new ArgumentExtractor<Dynamic>() {
@Override
public Dynamic extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
return DynamicFromArray.create(jsArguments, atIndex);
}
};
static final private ArgumentExtractor<ReadableMap> ARGUMENT_EXTRACTOR_MAP =
new ArgumentExtractor<ReadableMap>() {
@Override
public ReadableMap extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
return jsArguments.getMap(atIndex);
}
};
static final private ArgumentExtractor<Callback> ARGUMENT_EXTRACTOR_CALLBACK =
new ArgumentExtractor<Callback>() {
@Override
public @Nullable Callback extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
if (jsArguments.isNull(atIndex)) {
return null;
} else {
int id = (int) jsArguments.getDouble(atIndex);
return new com.facebook.react.bridge.CallbackImpl(jsInstance, id);
private static final ArgumentExtractor<Boolean> ARGUMENT_EXTRACTOR_BOOLEAN =
new ArgumentExtractor<Boolean>() {
@Override
public Boolean extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
return jsArguments.getBoolean(atIndex);
}
}
};
};
static final private ArgumentExtractor<Promise> ARGUMENT_EXTRACTOR_PROMISE =
new ArgumentExtractor<Promise>() {
@Override
public int getJSArgumentsNeeded() {
return 2;
}
private static final ArgumentExtractor<Double> ARGUMENT_EXTRACTOR_DOUBLE =
new ArgumentExtractor<Double>() {
@Override
public Double extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
return jsArguments.getDouble(atIndex);
}
};
@Override
public Promise extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
Callback resolve = ARGUMENT_EXTRACTOR_CALLBACK
.extractArgument(jsInstance, jsArguments, atIndex);
Callback reject = ARGUMENT_EXTRACTOR_CALLBACK
.extractArgument(jsInstance, jsArguments, atIndex + 1);
return new PromiseImpl(resolve, reject);
}
};
private static final ArgumentExtractor<Float> ARGUMENT_EXTRACTOR_FLOAT =
new ArgumentExtractor<Float>() {
@Override
public Float extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
return (float) jsArguments.getDouble(atIndex);
}
};
private static final ArgumentExtractor<Integer> ARGUMENT_EXTRACTOR_INTEGER =
new ArgumentExtractor<Integer>() {
@Override
public Integer extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
return (int) jsArguments.getDouble(atIndex);
}
};
private static final ArgumentExtractor<String> ARGUMENT_EXTRACTOR_STRING =
new ArgumentExtractor<String>() {
@Override
public String extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
return jsArguments.getString(atIndex);
}
};
private static final ArgumentExtractor<ReadableArray> ARGUMENT_EXTRACTOR_ARRAY =
new ArgumentExtractor<ReadableArray>() {
@Override
public ReadableArray extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
return jsArguments.getArray(atIndex);
}
};
private static final ArgumentExtractor<Dynamic> ARGUMENT_EXTRACTOR_DYNAMIC =
new ArgumentExtractor<Dynamic>() {
@Override
public Dynamic extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
return DynamicFromArray.create(jsArguments, atIndex);
}
};
private static final ArgumentExtractor<ReadableMap> ARGUMENT_EXTRACTOR_MAP =
new ArgumentExtractor<ReadableMap>() {
@Override
public ReadableMap extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
return jsArguments.getMap(atIndex);
}
};
private static final ArgumentExtractor<Callback> ARGUMENT_EXTRACTOR_CALLBACK =
new ArgumentExtractor<Callback>() {
@Override
public @Nullable Callback extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
if (jsArguments.isNull(atIndex)) {
return null;
} else {
int id = (int) jsArguments.getDouble(atIndex);
return new com.facebook.react.bridge.CallbackImpl(jsInstance, id);
}
}
};
private static final ArgumentExtractor<Promise> ARGUMENT_EXTRACTOR_PROMISE =
new ArgumentExtractor<Promise>() {
@Override
public int getJSArgumentsNeeded() {
return 2;
}
@Override
public Promise extractArgument(
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
Callback resolve =
ARGUMENT_EXTRACTOR_CALLBACK.extractArgument(jsInstance, jsArguments, atIndex);
Callback reject =
ARGUMENT_EXTRACTOR_CALLBACK.extractArgument(jsInstance, jsArguments, atIndex + 1);
return new PromiseImpl(resolve, reject);
}
};
private static final boolean DEBUG =
PrinterHolder.getPrinter().shouldDisplayLogMessage(ReactDebugOverlayTags.BRIDGE_CALLS);
@@ -152,8 +151,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
} else if (paramClass == Dynamic.class) {
return 'Y';
} else {
throw new RuntimeException(
"Got unknown param class: " + paramClass.getSimpleName());
throw new RuntimeException("Got unknown param class: " + paramClass.getSimpleName());
}
}
@@ -170,8 +168,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
} else if (returnClass == WritableArray.class) {
return 'A';
} else {
throw new RuntimeException(
"Got unknown return class: " + returnClass.getSimpleName());
throw new RuntimeException("Got unknown return class: " + returnClass.getSimpleName());
}
}
@@ -229,15 +226,13 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
return;
}
SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "processArguments")
.arg("method", mModuleWrapper.getName() + "." + mMethod.getName())
.flush();
.arg("method", mModuleWrapper.getName() + "." + mMethod.getName())
.flush();
try {
mArgumentsProcessed = true;
mArgumentExtractors = buildArgumentExtractors(mParameterTypes);
mSignature = buildSignature(
mMethod,
mParameterTypes,
(mType.equals(BaseJavaModule.METHOD_TYPE_SYNC)));
mSignature =
buildSignature(mMethod, mParameterTypes, (mType.equals(BaseJavaModule.METHOD_TYPE_SYNC)));
// Since native methods are invoked from a message queue executed on a single thread, it is
// safe to allocate only one arguments object per method that can be reused across calls
mArguments = new Object[mParameterTypes.length];
@@ -272,7 +267,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
Class paramClass = paramTypes[i];
if (paramClass == Promise.class) {
Assertions.assertCondition(
i == paramTypes.length - 1, "Promise must be used as last parameter only");
i == paramTypes.length - 1, "Promise must be used as last parameter only");
}
builder.append(paramTypeToChar(paramClass));
}
@@ -299,7 +294,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
} else if (argumentClass == Promise.class) {
argumentExtractors[i] = ARGUMENT_EXTRACTOR_PROMISE;
Assertions.assertCondition(
i == paramTypes.length - 1, "Promise must be used as last parameter only");
i == paramTypes.length - 1, "Promise must be used as last parameter only");
} else if (argumentClass == ReadableMap.class) {
argumentExtractors[i] = ARGUMENT_EXTRACTOR_MAP;
} else if (argumentClass == ReadableArray.class) {
@@ -307,8 +302,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
} else if (argumentClass == Dynamic.class) {
argumentExtractors[i] = ARGUMENT_EXTRACTOR_DYNAMIC;
} else {
throw new RuntimeException(
"Got unknown argument class: " + argumentClass.getSimpleName());
throw new RuntimeException("Got unknown argument class: " + argumentClass.getSimpleName());
}
}
return argumentExtractors;
@@ -323,16 +317,17 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
}
private String getAffectedRange(int startIndex, int jsArgumentsNeeded) {
return jsArgumentsNeeded > 1 ?
"" + startIndex + "-" + (startIndex + jsArgumentsNeeded - 1) : "" + startIndex;
return jsArgumentsNeeded > 1
? "" + startIndex + "-" + (startIndex + jsArgumentsNeeded - 1)
: "" + startIndex;
}
@Override
public void invoke(JSInstance jsInstance, ReadableArray parameters) {
String traceName = mModuleWrapper.getName() + "." + mMethod.getName();
SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "callJavaModuleMethod")
.arg("method", traceName)
.flush();
.arg("method", traceName)
.flush();
if (DEBUG) {
PrinterHolder.getPrinter()
.logMessage(
@@ -350,22 +345,26 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
}
if (mJSArgumentsNeeded != parameters.size()) {
throw new NativeArgumentsParseException(
traceName + " got " + parameters.size() + " arguments, expected " + mJSArgumentsNeeded);
traceName + " got " + parameters.size() + " arguments, expected " + mJSArgumentsNeeded);
}
int i = 0, jsArgumentsConsumed = 0;
try {
for (; i < mArgumentExtractors.length; i++) {
mArguments[i] = mArgumentExtractors[i].extractArgument(
jsInstance, parameters, jsArgumentsConsumed);
mArguments[i] =
mArgumentExtractors[i].extractArgument(jsInstance, parameters, jsArgumentsConsumed);
jsArgumentsConsumed += mArgumentExtractors[i].getJSArgumentsNeeded();
}
} catch (UnexpectedNativeTypeException e) {
throw new NativeArgumentsParseException(
e.getMessage() + " (constructing arguments for " + traceName + " at argument index " +
getAffectedRange(jsArgumentsConsumed, mArgumentExtractors[i].getJSArgumentsNeeded()) +
")",
e);
e.getMessage()
+ " (constructing arguments for "
+ traceName
+ " at argument index "
+ getAffectedRange(
jsArgumentsConsumed, mArgumentExtractors[i].getJSArgumentsNeeded())
+ ")",
e);
}
try {
@@ -388,10 +387,9 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
}
/**
* Determines how the method is exported in JavaScript:
* METHOD_TYPE_ASYNC for regular methods
* METHOD_TYPE_PROMISE for methods that return a promise object to the caller.
* METHOD_TYPE_SYNC for sync methods
* Determines how the method is exported in JavaScript: METHOD_TYPE_ASYNC for regular methods
* METHOD_TYPE_PROMISE for methods that return a promise object to the caller. METHOD_TYPE_SYNC
* for sync methods
*/
@Override
public String getType() {
@@ -1,50 +1,41 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import javax.annotation.Nullable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.systrace.Systrace;
import com.facebook.systrace.SystraceMessage;
import static com.facebook.react.bridge.ReactMarkerConstants.CONVERT_CONSTANTS_END;
import static com.facebook.react.bridge.ReactMarkerConstants.CONVERT_CONSTANTS_START;
import static com.facebook.react.bridge.ReactMarkerConstants.GET_CONSTANTS_END;
import static com.facebook.react.bridge.ReactMarkerConstants.GET_CONSTANTS_START;
import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE;
/**
* This is part of the glue which wraps a java BaseJavaModule in a C++
* NativeModule. This could all be in C++, but it's android-specific
* initialization code, and writing it this way is easier to read and means
* fewer JNI calls.
*/
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.systrace.Systrace;
import com.facebook.systrace.SystraceMessage;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
/**
* This is part of the glue which wraps a java BaseJavaModule in a C++ NativeModule. This could all
* be in C++, but it's android-specific initialization code, and writing it this way is easier to
* read and means fewer JNI calls.
*/
@DoNotStrip
public class JavaModuleWrapper {
@DoNotStrip
public class MethodDescriptor {
@DoNotStrip
Method method;
@DoNotStrip
String signature;
@DoNotStrip
String name;
@DoNotStrip
String type;
@DoNotStrip Method method;
@DoNotStrip String signature;
@DoNotStrip String name;
@DoNotStrip String type;
}
private final JSInstance mJSInstance;
@@ -93,10 +84,11 @@ public class JavaModuleWrapper {
// We do not support method overloading since js sees a function as an object regardless
// of number of params.
throw new IllegalArgumentException(
"Java Module " + getName() + " method name already registered: " + methodName);
"Java Module " + getName() + " method name already registered: " + methodName);
}
MethodDescriptor md = new MethodDescriptor();
JavaMethodWrapper method = new JavaMethodWrapper(this, targetMethod, annotation.isBlockingSynchronousMethod());
JavaMethodWrapper method =
new JavaMethodWrapper(this, targetMethod, annotation.isBlockingSynchronousMethod());
md.name = methodName;
md.type = method.getType();
if (md.type == BaseJavaModule.METHOD_TYPE_SYNC) {
@@ -126,8 +118,8 @@ public class JavaModuleWrapper {
final String moduleName = getName();
SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "JavaModuleWrapper.getConstants")
.arg("moduleName", moduleName)
.flush();
.arg("moduleName", moduleName)
.flush();
ReactMarker.logMarker(GET_CONSTANTS_START, moduleName);
BaseJavaModule baseJavaModule = getModule();

Some files were not shown because too many files have changed in this diff Show More