Summary:
It is possible that race conditions exist in access of scheduler and UIManager in Binding.cpp, such that deallocated or null schedulers/UIManagers could be passed as arguments into various functions, causing strange and exotic crashes down the line once garbage memory (or null pointers) are dereferenced.
I think it's possible that navigating away from a Fabric screen while there's high memory pressure could cause things to get deallocated more aggressively and cause scheduler and/or UIManager to disappear while mounting instructions are being created, for instance.
Reviewed By: mdvacca
Differential Revision: D15863193
fbshipit-source-id: a85cb71d88ea54826b40f44e788931dfc422f045
Summary:
The problem happens only from native debug build, i.e.
`NATIVE_BUILD_TYPE=Debug ./gradlew ...`
During Java exception happens, [only limited methods are allowed](https://developer.android.com/training/articles/perf-jni#exceptions_1).
RN uses smart pointer to manage JNI reference.
There is an assert() in smart pointer constructor that will call other JNI method and lead to VM crash.
Since assert() do things in debug build by default, the problem will not happens on native release build.
### Crash backtrace
Java exception happens:
```
java_vm_ext.cc:534] JNI DETECTED ERROR IN APPLICATION: JNI GetObjectRefType called with pending exception com.facebook.react.uimanager.IllegalViewOperationException: No ViewManager defined for class Text
java_vm_ext.cc:534] at com.facebook.react.uimanager.ViewManager com.facebook.react.uimanager.ViewManagerRegistry.get(java.lang.String) (ViewManagerRegistry.java:57)
java_vm_ext.cc:534] at com.facebook.react.uimanager.ViewManager com.facebook.react.uimanager.UIImplementation.resolveViewManager(java.lang.String) (UIImplementation.java:134)
java_vm_ext.cc:534] at com.facebook.react.bridge.WritableMap com.facebook.react.uimanager.UIManagerModule.computeConstantsForViewManager(java.lang.String) (UIManagerModule.java:325)
java_vm_ext.cc:534] at com.facebook.react.bridge.WritableMap com.facebook.react.uimanager.UIManagerModule.getConstantsForViewManager(java.lang.String) (UIManagerModule.java:319)
java_vm_ext.cc:534] at void com.facebook.react.bridge.queue.NativeRunnable.run() (NativeRunnable.java:-2)
java_vm_ext.cc:534] at void android.os.Handler.handleCallback(android.os.Message) (Handler.java:790)
java_vm_ext.cc:534] at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:99)
java_vm_ext.cc:534] at void com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(android.os.Message) (MessageQueueThreadHandler.java:29)
java_vm_ext.cc:534] at void android.os.Looper.loop() (Looper.java:164)
java_vm_ext.cc:534] at void com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run() (MessageQueueThreadImpl.java:232)
java_vm_ext.cc:534] at void java.lang.Thread.run() (Thread.java:764)
```
Native crash backtrace:
```
#00 pc 00000000000276f8 /system/lib64/libc.so (syscall+24)
https://github.com/facebook/react-native/issues/01 pc 0000000000027905 /system/lib64/libc.so (abort+101)
https://github.com/facebook/react-native/issues/02 pc 000000000052f32e /system/lib64/libart.so (art::Runtime::Abort(char const*)+558)
https://github.com/facebook/react-native/issues/03 pc 00000000006341a8 /system/lib64/libart.so (android::base::LogMessage::~LogMessage()+1016)
https://github.com/facebook/react-native/issues/04 pc 0000000000399339 /system/lib64/libart.so (art::JavaVMExt::JniAbort(char const*, char const*)+1657)
https://github.com/facebook/react-native/issues/05 pc 00000000003994c2 /system/lib64/libart.so (art::JavaVMExt::JniAbortV(char const*, char const*, __va_list_tag*)+82)
https://github.com/facebook/react-native/issues/06 pc 0000000000178aab /system/lib64/libart.so (art::ScopedCheck::AbortF(char const*, ...)+187)
https://github.com/facebook/react-native/issues/07 pc 00000000001785b8 /system/lib64/libart.so (art::ScopedCheck::CheckThread(_JNIEnv*)+472)
https://github.com/facebook/react-native/issues/08 pc 0000000000176871 /system/lib64/libart.so (art::ScopedCheck::Check(art::ScopedObjectAccess&, bool, char const*, art::JniValueType*)+801)
https://github.com/facebook/react-native/issues/09 pc 000000000017614a /system/lib64/libart.so (art::CheckJNI::GetObjectRefType(_JNIEnv*, _jobject*)+778)
https://github.com/facebook/react-native/issues/10 pc 0000000000123831 /data/app/com.facebook.react.uiapp-NEO_tjqQpFriZwGleZxJeQ==/lib/x86_64/libreactnativejni.so (_JNIEnv::GetObjectRefType(_jobject*)+49)
https://github.com/facebook/react-native/issues/11 pc 00000000001236b1 /data/app/com.facebook.react.uiapp-NEO_tjqQpFriZwGleZxJeQ==/lib/x86_64/libreactnativejni.so (facebook::jni::LocalReferenceAllocator::verifyReference(_jobject*) const+81)
https://github.com/facebook/react-native/issues/12 pc 0000000000046f40 /data/app/com.facebook.react.uiapp-NEO_tjqQpFriZwGleZxJeQ==/lib/x86_64/libfb.so (facebook::jni::base_owned_ref<_jthrowable*, facebook::jni::LocalReferenceAllocator>::base_owned_ref(_jthrowable*)+64)
https://github.com/facebook/react-native/issues/13 pc 0000000000046ef7 /data/app/com.facebook.react.uiapp-NEO_tjqQpFriZwGleZxJeQ==/lib/x86_64/libfb.so (facebook::jni::basic_strong_ref<_jthrowable*, facebook::jni::LocalReferenceAllocator>::basic_strong_ref(_jthrowable*)+39)
https://github.com/facebook/react-native/issues/14 pc 000000000003648b /data/app/com.facebook.react.uiapp-NEO_tjqQpFriZwGleZxJeQ==/lib/x86_64/libfb.so (_ZN8facebook3jni11adopt_localIP11_jthrowableEENS0_16basic_strong_refIT_NS0_23LocalReferenceAllocatorEEES5_+27)
https://github.com/facebook/react-native/issues/15 pc 0000000000036333 /data/app/com.facebook.react.uiapp-NEO_tjqQpFriZwGleZxJeQ==/lib/x86_64/libfb.so (facebook::jni::throwPendingJniExceptionAsCppException()+99)
https://github.com/facebook/react-native/issues/16 pc 000000000018652f /data/app/com.facebook.react.uiapp-NEO_tjqQpFriZwGleZxJeQ==/lib/x86_64/libreactnativejni.so (facebook::react::MethodInvoker::invoke(std::__ndk1::weak_ptr<facebook::react::Instance>&, facebook::jni::alias_ref<facebook::jni::detail::JTypeFor<facebook::react::JBaseJavaModule, facebook::jni::JObject, void>::_javaobject*>, folly::dynamic const&)+4559)
https://github.com/facebook/react-native/issues/17 pc 00000000001616fa /data/app/com.facebook.react.uiapp-NEO_tjqQpFriZwGleZxJeQ==/lib/x86_64/libreactnativejni.so (_ZN8facebook5react16JavaNativeModule26callSerializableNativeHookEjON5folly7dynamicE+954)
https://github.com/facebook/react-native/issues/18 pc 000000000021bbd6 /data/app/com.facebook.react.uiapp-NEO_tjqQpFriZwGleZxJeQ==/lib/x86_64/libreactnativejni.so (_ZN8facebook5react14ModuleRegistry26callSerializableNativeHookEjjON5folly7dynamicE+486)
https://github.com/facebook/react-native/issues/19 pc 000000000022d90b /data/app/com.facebook.react.uiapp-NEO_tjqQpFriZwGleZxJeQ==/lib/x86_64/libreactnativejni.so (_ZN8facebook5react16JsToNativeBridge26callSerializableNativeHookERNS0_10JSExecutorEjjON5folly7dynamicE+75)
https://github.com/facebook/react-native/issues/20 pc 000000000004a6fa /data/app/com.facebook.react.uiapp-NEO_tjqQpFriZwGleZxJeQ==/lib/x86_64/libjscexecutor.so (facebook::react::JSIExecutor::nativeCallSyncHook(facebook::jsi::Value const*, unsigned long)+202)
https://github.com/facebook/react-native/issues/21 pc 000000000004b7a2 /data/app/com.facebook.react.uiapp-NEO_tjqQpFriZwGleZxJeQ==/lib/x86_64/libjscexecutor.so
https://github.com/facebook/react-native/issues/22 pc 0000000000056475 /data/app/com.facebook.react.uiapp-NEO_tjqQpFriZwGleZxJeQ==/lib/x86_64/libjscexecutor.so
https://github.com/facebook/react-native/issues/23 pc 00000000000c3a0a /data/app/com.facebook.react.uiapp-NEO_tjqQpFriZwGleZxJeQ==/lib/x86_64/libjsc.so
```
Java exception code from [ViewManagerRegistry.java](https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerRegistry.java#L45-L58) :
```java
public ViewManager get(String className) {
ViewManager viewManager = mViewManagers.get(className);
if (viewManager != null) {
return viewManager;
}
if (mViewManagerResolver != null) {
viewManager = mViewManagerResolver.getViewManager(className);
if (viewManager != null) {
mViewManagers.put(className, viewManager);
return viewManager;
}
}
throw new IllegalViewOperationException("No ViewManager defined for class " + className);
}
```
It is an expected exception as [legacy JS try to find view manager](https://github.com/facebook/react-native/blob/master/Libraries/ReactNative/PaperUIManager.js#L44-L50) and Text has no ViewManager registered in fact.
From C++ assert:
`adopt_local` will call to base_owned_ref() and [there is an assert to ensure JNI reference type](https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/jni/first-party/fb/include/fb/fbjni/References-inl.h#L203-L209).
```C++
template<typename T, typename Alloc>
inline facebook::jni::base_owned_ref<T, Alloc>::base_owned_ref(
javaobject reference) noexcept
: storage_(reference) {
assert(Alloc{}.verifyReference(reference));
internal::dbglog("New wrapped ref=%p this=%p", get(), this);
}
```
In the verifyReference(), [there is a GetObjectRefType() call which is an invalid call at exception pending state](https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/jni/first-party/fb/include/fb/fbjni/ReferenceAllocators-inl.h#L57-L62).
```C++
inline bool LocalReferenceAllocator::verifyReference(jobject reference) const noexcept {
if (!reference || !internal::doesGetObjectRefTypeWork()) {
return true;
}
return internal::getEnv()->GetObjectRefType(reference) == JNILocalRefType;
}
```
The fix moves `adopt_local()` wrapping after `ExceptionClear()` and we could call `GetObjectRefType()` without problems.
## Changelog
[Android] [Fixed] - Fix Android native debug build assert crash
NOTE this might be ignored in RN release changelog.
Since the problem should exist for years and no user tried native debug build.
Pull Request resolved: https://github.com/facebook/react-native/pull/25263
Test Plan:
Try to run RNTester from native debug build and make sure no crash happens.
(It is a launch crash and should be easy to verify)
`NATIVE_BUILD_TYPE=Debug ./gradlew clean :RNTester:android:app:installDebug`
Differential Revision: D15873691
Pulled By: cpojer
fbshipit-source-id: fb93b85daa1136cdf44e7fd7f217a2767391d8dd
Summary: This diff forces the method: scheduler.constraintSurfaceLayout to run on the JS thread.
Reviewed By: JoshuaGross
Differential Revision: D15845768
fbshipit-source-id: de2aa69f301770aaf6cb7c3f5670548a3b6110df
Summary: Scheduler.startSurface accepts LayoutConstraints and LayoutContext, but for some reason we don't use these on Android. This diff adds new methods to Binding and FabricUIManager to start a surface with the provided measurespecs. I created new methods to avoid affecting the functionality of any surfaces already using Fabric, but if we want this behavior everywhere then I can just add it to the existing `addRootView` and `startSurface`.
Reviewed By: JoshuaGross, shergin
Differential Revision: D15810990
fbshipit-source-id: 6cd9a58b125461f91253458905405298cfb723ce
Summary: Just adding a few systrace sections to add perf visibility in a few more areas.
Reviewed By: ejanzer
Differential Revision: D15823394
fbshipit-source-id: 6ac1773cbd8e01a747ad015726e16c0bf0e8596b
Summary:
There's an issue with TextInput on Android where if you have TalkBack enabled, double tapping doesn't focus the text input. It turns out this is because we ignore all focus events that aren't from JS in ReactEditText. This diff makes an exception for the accessibility click event.
I think this should also fix https://github.com/facebook/react-native/issues/17624
Reviewed By: lunaleaps
Differential Revision: D15818103
fbshipit-source-id: 354728b58f1023c4d44edd48337c8daa8ea15c0c
Summary: Easy diff to create a ReactFeatureFlag to enabled logging in Fabric
Reviewed By: JoshuaGross
Differential Revision: D15803582
fbshipit-source-id: d735f24850bddf43c27b97d006100cbb8f0cc6e3
Summary:
This PR only fixes a one small orthographic error
Pull Request resolved: https://github.com/facebook/react-native/pull/25245
Differential Revision: D15796478
Pulled By: hramos
fbshipit-source-id: ccb811b43b0d2efc5d97ba335b60531a0fcbda10
Summary:
Modify the wrong word in the comment of NativeViewHierarchyManager.java.
Fix the explanation of the code to avoid misunderstanding.
## Changelog
[Android] [Fixed] - Fix the explanation of the code to avoid misunderstanding.
Pull Request resolved: https://github.com/facebook/react-native/pull/25235
Differential Revision: D15779249
Pulled By: cpojer
fbshipit-source-id: d4e7baa9ea9be5551feed8f643fe9774b3226bd8
Summary:
`fbsource//xplat/js/react-native-github/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni:jni` is a shared library that depends on `fbjni` (also another shared library). In dev and prod, I think `turbomodule/core/jni:jni` was pulling in `fbjni` from its `react_native_target("jni/react/jni:jni")` dependency even though `FBJNI_TARGET` wasn't an exported_dep of `react_native_target("jni/react/jni:jni")`. In `android_automation_cameracore_release_build`, however, this wasn't happening, which led to that build failing to compile.
In this diff, I'm explicitly making `FBJNI_TARGET` a dependency of `fbsource//xplat/js/react-native-github/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni:jni`. This unbreaks `android_automation_cameracore_release_build`.
Reviewed By: fkgozali
Differential Revision: D15758160
fbshipit-source-id: db20c127a888b0cf68aea592de6a2e380c455c1d
Summary:
D14014668 introduced support for nesting views within Text on Android. Part of the implementation involved accessing the UIManagerModule from ReactTextView through context. This doesn't work in bridgeless RN because we have no UIManagerModule, and the ReactContext has no Catalyst instance. Trying to access the Catalyst instance from ReactContext throws an exception if it doesn't exist, so i'm just adding a simple check here to make sure the instance exists before proceeding.
This means that this feature won't work in bridgeless mode, but that's ok for now - eventually we want to change the way this works so that it doesn't rely on accessing views in Java, which is potentially unsafe (there's nothing to stop you from mutating the views, and cpp/js would never know about it).
Reviewed By: mdvacca
Differential Revision: D15703100
fbshipit-source-id: 0448d55b8345fc707a25210a505cb6ac520c708a
Summary:
These changes were originally landed in D15327683. Unfortunately, I had to back these out because they revelaled problems with our TurboModules infra. Those problems have since been fixed, so I think it's safe for us to re-land these changes.
Please refer to D15327683 for a description.
Differential Revision: D15739355
fbshipit-source-id: 69bb3cec0731ba325f60c6c8459426546c79b54d
Summary:
## Description
CompositeReactPackage will now eagerly initialize all NativeModules inside the TurboReactPackages. Before it would just crash the program because calling `createNativeModules()` on the TurboReactPackage instance. Longer term, we should make CompositeReactPackage a TurboReactPackage.
## Why am I making this change?
I made MainReactPackage into a TurboReactPackge. But ExpressWifiTechnician uses MainReactPackage to create a CompositeReactPackage:
**java/com/expresswifi/technician/MainActivity.java**
```
protected ReactPackage getPackage() {
ReactInstanceManager reactInstanceManager = getReactInstanceManager();
Nullable DevSupportManager devSupportManager = null;
if (reactInstanceManager != null) {
devSupportManager = reactInstanceManager.getDevSupportManager();
}
return new CompositeReactPackage(
super.getPackage(),
mXWFTechnicianReactPackage,
new RNFusedLocationPackage(),
mXWFTechnicialMobileConfigPackageProvider.get(devSupportManager));
}
```
**java/com/facebook/catalyst/shell/MainReactActivity.java**
```
public abstract class MainReactActivity extends AbstractReactActivity {
protected ReactPackage getPackage() {
return new MainReactPackage();
}
}
```
Reviewed By: fkgozali
Differential Revision: D15738677
fbshipit-source-id: 3220dfe6434de56f2917c77fb21acef4cfc79278
Summary: Removes `unsetOwner` from Yoga. This was temporarily for patching a crash.
Reviewed By: colriot
Differential Revision: D15737613
fbshipit-source-id: 8ab93ecf7ffb913df6207fe5db47a8cc93eded2c
Summary:
Scrolling improvements in ReactAndroid:
1.
Issue: With current ReactHorizontalScrollView behavior, it treats all views as focusable, regardless of if they are in view or not. This is fine for non-paged horizontal scroll view, but when paged this allows focus on elements that are not within the current page. Combined with logic to scroll to the focused view, this breaks the paging for ReactHorizontalScrollView.
Fix: limit the focusable elements to only elements that are currently in view when ReactHorizontalScrollView has paging enabled
2.
Issue: When keyboard is attached and user tries to navigate through Tab key, Scroll views do not scroll to the focused child.
Since ReactScrollView handles layout changes on JS side, it does not call super.onlayout due to which mIsLayoutDirty flag in android ScrollView remains true and prevents scrolling to child when requestChildFocus is called.
Fix: To fix the focus navigation, we are overriding requestChildFocus method in ReactScrollView. We are not checking any dirty layout flag and scrolling to child directly. This will fix focus navigation issue for KeyEvents which are not handled by android's ScrollView, for example: KEYCODE_TAB. Same applies to ReactHorizontalScrollView.
3.
Set Android ScrollView to be non-focusable when scroll is disabled. Prior to this change, non-scrollable Scrollview would still be focusable, causing a poor keyboarding experience
## Changelog
[Android] [Fixed] Scrolling improvements in ReactAndroid
Pull Request resolved: https://github.com/facebook/react-native/pull/25105
Differential Revision: D15737563
Pulled By: mdvacca
fbshipit-source-id: 0d57563415c68668dc1acb05fb3399e6645c9595
Summary:
React Native on Android has currently been focused and targeted at using an Activity for its main form of instantiation.
While this has probably worked for most companies and developers, you lose some of the modularity of a more cohesive application when working in a "brown-field" project that is currently native. This hurts more companies that are looking to adopt React Native and slowly implement it in a fully native application.
A lot of developers follow Android's guidelines of using Fragments in their projects, even if it is a debated subject in the Android community, and this addition will allow others to embrace React Native more freely. (I even assume it could help with managing navigation state in applications that contain a decent amount of Native code and would be appreciated in those projects. Such as sharing the Toolbar, TabBar, ViewPager, etc in Native Android)
Even with this addition, a developer will still need to host the fragment in an activity, but now that activity can contain native logic like a Drawer, Tabs, ViewPager, etc.
Test plan (required)
We have been using this class at Hudl for over a couple of months and have found it valuable.
If the community agrees on the addition, I can add documentation to the Android sections to include notes about the potential of this Fragment.
If the community agrees on the addition, I can update one or more of the examples in the /Examples folder and make use of the Fragment, or even create a new example that uses a native layout manager like Drawer, Tabs, Viewpager, etc)
Make sure tests pass on both Travis and Circle CI.
_To Note:_
There is also talk of using React Native inside Android Fragment's without any legit documentation, this could help remedy some of that with more documentation included in this PR https://facebook.github.io/react-native/releases/0.26/docs/embedded-app-android.html#sharing-a-reactinstance-across-multiple-activities-fragments-in-your-app
Others have also requested something similar and have a half-baked solution as well http://stackoverflow.com/questions/35221447/react-native-inside-a-fragment
Release Notes
[ANDROID][FEATURE][ReactAndroid/src/main/java/com/facebook/react/ReactFragment.java] - Adds support for Android's Fragment system. This allows for a more hybrid application.
Reviewed By: cpojer
Differential Revision: D15731340
fbshipit-source-id: 74b7aaedcfd6ad6e074ff911cd7f18a5111caf5c
Summary: Listen to NodeLayout event and passes this event callback to java layer along with the information whether layout or measure was done in this pass
Reviewed By: davidaurelio
Differential Revision: D15696021
fbshipit-source-id: 8c5ca69330a9baca26b77052d4965cc67fe97c75
Summary: This diff creates a new react feature flag to enable extra logging on React Web Views
Reviewed By: RSNara
Differential Revision: D15729871
fbshipit-source-id: 931d4a1b022c6a405228bf896b50ecc7a44478d1
Summary: `ReactTurboModuleManagerDelegate` only understands `TurboReactPackage`s. So, we need to convert `FBMainReactPackage` and all its dependent packages into `TurboReactPackage`.
Reviewed By: fkgozali
Differential Revision: D15711546
fbshipit-source-id: df626d542a6477b116c867299219156423c6364a
Summary: To implement the `getModule` method of `TurboReactPackages`, we need to be able to access the JS Names of NativeModule classes.
Reviewed By: fkgozali
Differential Revision: D15711544
fbshipit-source-id: 51a649d08410557a4bdbf20d065bf98646a8d18a
Summary:
When `ModuleHolder` instantiates `NativeModules`, it calls the `initialize()` method. We should replicate this call in the TurboModule system.
`NativeModule.initialize()` is meant to be called after ReactApplicationContext is initialized. TurboModuleManager is initialized after ReactApplicationContext is initialized. Therefore, after we create the TurboModule, it should be safe to call `initialize()` on it.
Reviewed By: mdvacca
Differential Revision: D15711540
fbshipit-source-id: c2ef1a2ab164996bfc5716d81b3b3c716bf0e120
Summary:
... and slighly new behaviour for one of them.
The method does nothing if given `key` already exists in the container.
This diff finishes the transition of ContextContainer from an internal bag of things with unclear yet ownership into a legit dedicated dependency injection container for the product code.
The original names of methods imply that the container can have only one object of a given type which is no longer true. The new API is much more generic and idiomatic to C++, it mimics `std:map` API which is intuitive to anyone who familiar with C++ containers.
Besides the naming, `insert` method changed the semantic a bit; now it does nothing in case of inserting an object with a key that already exists. That might seem counterintuitive for "normal" people, but C++ has some wired reasons for that and, hopefully, it's expected behavior in the C++ community.
Fun fact: We need this to fix hot-reload.
Reviewed By: sahrens
Differential Revision: D15681736
fbshipit-source-id: 194f342528446a911eaf072ba3a94a5d8af3cb52
Summary:
Original commit changeset: e295dafdab7a
I'm backing this out because it's broken Catalyst. The fixes are in D15711539, but it could take some time to review and land them.
Reviewed By: rickhanlonii
Differential Revision: D15714896
fbshipit-source-id: c2c555a52d3d140dfdea7d54ccd8d3102c22a1c6
Summary: Move PtrJNodeMap to header file so that it can be accessed in events subscribers outside yoga
Reviewed By: davidaurelio
Differential Revision: D15619629
fbshipit-source-id: 1bf213efd38ec7bcac6a38070f21fa837c5f17da
Summary:
`/*` is the standard throughout open source code. For example, Firefox uses single /*: https://hg.mozilla.org/mozilla-central/file/21d22b2f541258d3d1cf96c7ba5ad73e96e616b5/gfx/ipc/CompositorWidgetVsyncObserver.cpp#l3
In addition, Rust considers `/**` to be a doc comment (similar to Javadoc) and having such a comment at the beginning of the file causes `rustc` to barf.
Note that some JavaScript tooling requires `/**`. This is OK since JavaScript files were not covered by the linter in the first place, but it would be good to have that tooling fixed too.
Reviewed By: zertosh
Differential Revision: D15640366
fbshipit-source-id: b4ed4599071516364d6109720750d6a43304c089
Summary:
`setTimeout` inside a headless JS task does not always works; the function does not get invoked until the user starts an `Activity`.
This was attempted to be used in the context of widgets. When the widget update or user interaction causes the process and React context to be created, the headless JS task may run before other app-specific JS initialisation logic has completed. If it's not possible to change the behaviour of the pre-requisites to be synchronous, then the headless JS task blocks such asynchronous JS work that it may depend on. A primitive solution is the use of `setTimeout` in order to wait for the pre-conditions to be met before continuing with the rest of the headless JS task. But as the function passed to `setTimeout` is not always called, the task will not run to completion.
This PR solves this scenario by allowing the task to be retried again with a delay. If the task returns a promise that resolves to a `{'timeout': number}` object, `AppRegistry.js` will not notify that the task has finished as per master, instead it will tell `HeadlessJsContext` to `startTask` again (cleaning up any posted `Runnable`s beforehand) via a `Handler` within the `HeadlessJsContext`.
Documentation also updated here: https://github.com/facebook/react-native-website/pull/771
### AppRegistry.js
If the task provider does not return any data, or if the data it returns does not contain `timeout` as a number, then it behaves as `master`; notifies that the task has finished. If the response does contain `{timeout: number}`, then it will attempt to queue a retry. If that fails, then it will behaves as if the task provider returned no response i.e. behaves as `master` again. If the retry was successfully queued, then there is nothing to do as we do not want the `Service` to stop itself.
### HeadlessJsTaskSupportModule.java
Similar to notify start/finished, we simply check if the context is running, and if so, pass the request onto `HeadlessJsTaskContext`. The only difference here is that we return a `Promise`, so that `AppRegistry`, as above, knows whether the enqueuing failed and thus needs to perform the usual task clean-up.
### HeadlessJsTaskContext.java
Before retrying, we need to clean-up any timeout `Runnable`'s posted for the first attempt. Then we need to copy the task config so that if this retry (second attempt) also fails, then on the third attempt (second retry) we do not run into a consumed exception. This is also why in `startTask` we copy the config before putting it in the `Map`, so that the initial attempt does leave the config's in the map as consumed. Then we post a `Runnable` to call `startTask` on the main thread's `Handler`. We use the same `taskId` because the `Service` is keeping track of active task IDs in order to calculate whether it needs to `stopSelf`. This negates the need to inform the `Service` of a new task id and us having to remove the old one.
## Changelog
[Android][added] - Allow headless JS tasks to return a promise that will cause the task to be retried again with the specified delay
Pull Request resolved: https://github.com/facebook/react-native/pull/23231
Differential Revision: D15646870
fbshipit-source-id: 4440f4b4392f1fa5c69aab7908b51b7007ba2c40
Summary:
Add example showing regression before this fix is applied.
https://github.com/facebook/react-native/pull/18187 Was found to introduce a regression in some internal facebook code-base end to end test which couldn't be shared. I was able to create a reproducible demo of a regression I found, and made a fix for it. Hopefully this will fix the internal test, such that the pr can stay merged.
## Changelog
[GENERAL] [Fixed] - Fix connection of animated nodes and scroll offset with useNativeDriver.
Pull Request resolved: https://github.com/facebook/react-native/pull/24177
Reviewed By: rickhanlonii
Differential Revision: D14845617
Pulled By: cpojer
fbshipit-source-id: 1f121dbe773b0cde2adf1ee5a8c3c0266034e50d
Summary: This moves the Android related files to FB internal and moves the BUCK deps around.
Reviewed By: fkgozali
Differential Revision: D15392573
fbshipit-source-id: 251d2766729ed42a6fe312b3ab9c6b8f1a8c46d1
Summary: This moves the Toolbar Java files out RN and into our internal React shell.
Reviewed By: fkgozali
Differential Revision: D15469205
fbshipit-source-id: 15298505d74260618eb89673deb12d1b837b559f
Summary: Adding TurboModule for PlatformConstantsAndroid, and adding to Catalyst and Venice
Reviewed By: mdvacca
Differential Revision: D15630344
fbshipit-source-id: df6d5868cd3c9f54297bfea58683c8c1fd9375f0
Summary: Making DeviceInfo support TurboModule on Android; implementing the interface in the Java class and setting up codegen for the spec.
Reviewed By: mdvacca
Differential Revision: D15616194
fbshipit-source-id: 6326f23d95295e570df6f6c88289102ac733def7
Summary:
## Description
To initialize `TurboModuleManager`, we first need to wait until `ReactContext` is initialized. Then, we get the `TurboModuleManager` instance and assign it as the `TurboModuleRegistry` of `CatalystInstanceImpl`. This allows `CatalystInstanceImpl` to return TurboModules from its `getNativeModule` method. In `FbReactFragment`, we also wait until the `ReactContext` is initialized before then eagerly initialize a bunch of NativeModules. All this waiting is done by adding instances of `ReactInstanceEventListener` to `ReactInstanceManager`'s `mReactInstanceEventListeners` synchronized Set. When the `ReactContext` is finally initialized, we loop over this set and invoke all the listeners.
## Problem
We want to initialize `TurboModuleManager` and set it as the `TurboModuleRegistry` of `CatalystInstanceImpl` before we start eagerly initializing our NativeModules. Why? Because otherwise TurboModules that need to be eagerly initialized won't be. The fact that we're using a Set to manage the `ReactInstanceEventListener`s means that our listeners can be invoked in any order. This is bad because we can start to eagerly initialize NativeModules before we've had the chance to assign `TurboModuleManager` as the `TurboModuleRegistry` of `CatalystInstanceImpl`. In development, this race was leading to the following crash:
```
06-05 11:11:02.020 10461 10617 E AndroidRuntime: FATAL EXCEPTION: CombinedTP8
06-05 11:11:02.020 10461 10617 E AndroidRuntime: Process: com.facebook.wakizashi, PID: 10461
06-05 11:11:02.020 10461 10617 E AndroidRuntime: java.lang.AssertionError: Could not find module with name PrimedStorage
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at com.facebook.infer.annotation.Assertions.assertNotNull(Assertions.java:35)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at com.facebook.react.bridge.NativeModuleRegistry.getModule(NativeModuleRegistry.java:147)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at com.facebook.react.bridge.CatalystInstanceImpl.getNativeModule(CatalystInstanceImpl.java:444)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at com.facebook.fbreact.fragment.FbReactFragment$4$1.run(FbReactFragment.java:418)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at com.facebook.common.executors.WrappingExecutorService$1.run(WrappingExecutorService.java:82)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at com.facebook.common.combinedthreadpool.queue.CombinedSimpleTask.run(CombinedSimpleTask.java:81)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at com.facebook.common.combinedthreadpool.queue.CombinedLifetimeThreadFactory$1.run(CombinedLifetimeThreadFactory.java:40)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at com.facebook.common.executors.NamedThreadFactory$1.run(NamedThreadFactory.java:53)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at java.lang.Thread.run(Thread.java:764)
```
## Diagnosing the crash
It looks like `NativeModuleRegistry.getModule` was throwing an error because `PrimedStorage` was null. `PrimedStorage` was turned into a TurboModule, so of course it wouldn't be in the `NativeModuleRegistry`. It should be in the `TurboModuleRegistry`. So, I placed an assertion in `CatalystInstanceImpl`:
```
Override
public NativeModule getNativeModule(String moduleName) {
Assertions.assertNotNull(mTurboModuleRegistry, "TurboModuleRegsitry is not null");
if (mTurboModuleRegistry != null) {
TurboModule turboModule = mTurboModuleRegistry.getModule(moduleName);
if (turboModule != null) {
return (NativeModule)turboModule;
}
}
return mNativeModuleRegistry.getModule(moduleName);
}
```
Sure enough, this assertion started tripping, which meant that `mTurboModuleRegistry` was null. From this information, I hypothesized that we started to eagerly initialize our NativeModules before `TurboModuleManager` was initialized. To verify this hypothesis, I added logging statements in each `ReactInstanceEventListener`: P65477469. `eagerInitializeReactNativeComponents (START)` documents when we start to eagerly intialize our NativeModules. `getReactInstanceManager (START)` documents when we start to initialize `TurboModuleManager` inside `FbReactInstanceHolder.getReactInstanceManager` method. Sure enough, when the program finally crashed, I saw in our logs that we started eagerly initializing our NativeModules before we initialized the TurboModuleManager:
```
06-05 11:11:01.951 10461 10617 V Ramanpreet: eagerInitializeReactNativeComponents (START): 1559758261951
06-05 11:11:01.956 10461 10461 V Ramanpreet: getReactInstanceManager (START): 1559758261956
06-05 11:11:01.958 10461 10461 D SoLoader: About to load: libturbomodulejsijni.so
06-05 11:11:01.960 10461 10461 D SoLoader: libturbomodulejsijni.so not found on /data/data/com.facebook.wakizashi/lib-zstd
06-05 11:11:01.960 10461 10461 D SoLoader: libturbomodulejsijni.so not found on /data/data/com.facebook.wakizashi/lib-xzs
06-05 11:11:01.960 10461 10461 D SoLoader: libturbomodulejsijni.so not found on /data/data/com.facebook.wakizashi/lib-assets
06-05 11:11:01.961 10461 10461 D SoLoader: libturbomodulejsijni.so found on /data/data/com.facebook.wakizashi/lib-main
06-05 11:11:01.965 10461 10461 D SoLoader: Loading lib dependencies: [libfb.so, libfbjni.so, libglog.so, libdouble-conversion.so, libxplat_jsi_jsiAndroid.so, libxplat_jsi_JSIDynamicAndroid.so, libfbsystrace.so, libmemalign16.so, libgnustl_shared.so, libm.so, libc.so]
06-05 11:11:01.999 10461 10769 D SoLoader: init exiting
06-05 11:11:01.999 10461 10461 D SoLoader: Loaded: libturbomodulejsijni.so
06-05 11:11:01.999 10461 10461 D SoLoader: About to load: libfb4aturbomodulemanagerdelegate.so
06-05 11:11:01.999 10461 10769 W fb4a.ImagePipelineFactory: ImagePipelineFactory has already been initialized! `ImagePipelineFactory.initialize(...)` should only be called once to avoid unexpected behavior.
06-05 11:11:02.002 10461 10461 D SoLoader: libfb4aturbomodulemanagerdelegate.so not found on /data/data/com.facebook.wakizashi/lib-zstd
06-05 11:11:02.002 10461 10461 D SoLoader: libfb4aturbomodulemanagerdelegate.so not found on /data/data/com.facebook.wakizashi/lib-xzs
06-05 11:11:02.002 10461 10461 D SoLoader: libfb4aturbomodulemanagerdelegate.so not found on /data/data/com.facebook.wakizashi/lib-assets
06-05 11:11:02.004 10461 10461 D SoLoader: libfb4aturbomodulemanagerdelegate.so found on /data/data/com.facebook.wakizashi/lib-main
06-05 11:11:02.007 10461 10461 D SoLoader: Loading lib dependencies: [libturbomodulejsijni.so, libfb.so, libfbjni.so, libxplat_jsi_jsiAndroid.so, libxplat_jsi_JSIDynamicAndroid.so, libreactnativejni.so, libmemalign16.so, libgnustl_shared.so, libc.so]
06-05 11:11:02.020 10461 10617 E AndroidRuntime: FATAL EXCEPTION: CombinedTP8
06-05 11:11:02.020 10461 10617 E AndroidRuntime: Process: com.facebook.wakizashi, PID: 10461
06-05 11:11:02.020 10461 10617 E AndroidRuntime: java.lang.AssertionError: Could not find module with name PrimedStorage
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at com.facebook.infer.annotation.Assertions.assertNotNull(Assertions.java:35)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at com.facebook.react.bridge.NativeModuleRegistry.getModule(NativeModuleRegistry.java:147)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at com.facebook.react.bridge.CatalystInstanceImpl.getNativeModule(CatalystInstanceImpl.java:444)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at com.facebook.fbreact.fragment.FbReactFragment$4$1.run(FbReactFragment.java:418)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at com.facebook.common.executors.WrappingExecutorService$1.run(WrappingExecutorService.java:82)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at com.facebook.common.combinedthreadpool.queue.CombinedSimpleTask.run(CombinedSimpleTask.java:81)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at com.facebook.common.combinedthreadpool.queue.CombinedLifetimeThreadFactory$1.run(CombinedLifetimeThreadFactory.java:40)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at com.facebook.common.executors.NamedThreadFactory$1.run(NamedThreadFactory.java:53)
06-05 11:11:02.020 10461 10617 E AndroidRuntime: at java.lang.Thread.run(Thread.java:764)
06-05 11:11:02.038 1647 1667 I WifiService: requestActivityInfo uid=1000
06-05 11:11:02.038 1647 1667 I WifiService: reportActivityInfo uid=1000
06-05 11:11:02.038 1647 1667 I WifiService: getSupportedFeatures uid=1000
06-05 11:11:02.044 1647 1667 E BluetoothAdapter: Bluetooth binder is null
06-05 11:11:02.049 1647 1667 E KernelCpuSpeedReader: Failed to read cpu-freq: /sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state (No such file or directory)
06-05 11:11:02.050 1647 1667 E BatteryExternalStatsWorker: modem info is invalid: ModemActivityInfo{ mTimestamp=0 mSleepTimeMs=0 mIdleTimeMs=0 mTxTimeMs[]=[0, 0, 0, 0, 0] mRxTimeMs=0 mEnergyUsed=0}
06-05 11:11:02.057 2147 10435 W ctxmgr : [AclManager]No 2 for (accnt=account#-517948760#, com.google.android.gms(10013):IndoorOutdoorProducer, vrsn=13280000, 0, 3pPkg = null , 3pMdlId = null , pid = 2147). Was: 3 for 57, account#-517948760#
06-05 11:11:02.077 10461 10461 D SoLoader: Loaded: libfb4aturbomodulemanagerdelegate.so
06-05 11:11:02.079 10461 10461 V Ramanpreet: getReactInstanceManager (END): 1559758262079
```
Reviewed By: mdvacca
Differential Revision: D15676746
fbshipit-source-id: a7ac02d868abf31c5d664b10f70b6db247f388f5
Summary:
## Summary
If a NativeModule Spec interface extends `TurboModule`, we want to make the auto-generated Java base class for that NativeModule to implement `com.facebook.react.turbomodule.core.interfaces.TurboModule`. This makes it so that our Android code recognizes that Java module as a TurboModule.
When this diff lands, all internal FB4A NativeModules will start going through the TurboModule system.
Reviewed By: fkgozali
Differential Revision: D15327683
fbshipit-source-id: e295dafdab7a0e130820318aeaf0cafa41487689
Summary: This diff introduces `TurboModuleManagerDelegate` in Fb4a and Workplace. `Fb4aTurboModuleManagerDelegate` is responsible for creating TurboModules for Fb4a. `WorkTurboModuleManagerDelegate` is responsible for creating TurboModules for Workplace.
Reviewed By: mdvacca
Differential Revision: D15268563
fbshipit-source-id: c254c31856c59b3551bfe54b25c715c848646c5a
Summary:
### Problem
According to https://github.com/facebook/react-native/issues/9145, the `--port` setting is not respected when executing `react-native run-android`. The templates that report things like what port the dev server runs on are hard coded as well.
### Solution
This commit replaces the hardcoded instances of port 8081 on Android with a build configuration property. This allows setting of the port React Native Android connects to for the local build server.
For this change to work, there must also be an update to the react native CLI to pass along this setting:
https://github.com/react-native-community/react-native-cli/compare/master...nhunzaker:9145-android-no-port-hardcode-cli
To avoid some noise on their end, I figured I wouldn't submit a PR until it's this approach is deemed workable.
## Changelog
[Android][fixed] - `react-native run-android --port <x>` correctly connects to dev server and related error messages display the correct port
Pull Request resolved: https://github.com/facebook/react-native/pull/23616
Differential Revision: D15645200
Pulled By: cpojer
fbshipit-source-id: 3bdfd458b8ac3ec78290736c9ed0db2e5776ed46
Summary:
With JSI based architecture, there will be more and more C++ native code involved.
Original NDK builder in RN only supports release build and that's not reasonable for native debugging.
This change introduces a way to build native code in debuggable version.
Simply add `NATIVE_BUILD_TYPE=Debug` environment variable during gradle build,
e.g.
`NATIVE_BUILD_TYPE=Debug ./gradlew clean :ReactAndroid:assembleDebug`
## Changelog
[Android] [Added] - Add native debug build support to improve debugging DX
Pull Request resolved: https://github.com/facebook/react-native/pull/25147
Differential Revision: D15628533
Pulled By: cpojer
fbshipit-source-id: 8f5b54c4580824452d2a1236a7bd641889b001ec
Summary: `TurboModuleManagerDelegate` is an interface used to query/create TurboModules. It doesn't need to know anything about `ReactApplicationContext`. So, I'm removing all references of `ReactApplicationContext` from this class.
Reviewed By: mdvacca
Differential Revision: D15590552
fbshipit-source-id: 761d3ed71f124955f9c6b997e68a7a8338182126
Summary: Move PtrJNodeMap to header file so that it can be accessed in events subscribers outside yoga
Reviewed By: davidaurelio
Differential Revision: D15602627
fbshipit-source-id: bb5bd5bbf8dcb279f5f87a4fd7287909d4e895d8
Summary:
Co-Authored: zamotany
With React Native 0.59.8 the app keeps crashing with indexed RAM bundle on Android with the following error:
```
2019-05-09 11:58:06.684 2793-2856/? E/AndroidRuntime: FATAL EXCEPTION: mqt_js
Process: com.ramtestapp, PID: 2793
com.facebook.jni.CppException: getPropertyAsObject: property '__fbRequireBatchedBridge' is not an Object
no stack
at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:29)
at android.os.Looper.loop(Looper.java:193)
at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:232)
at java.lang.Thread.run(Thread.java:764)
```
After investigation we found that when using any bundle, let it be non-ram, FIle RAM bundle or Index RAM bundle, the `CatalystInstanceImpl.java` is always using `loadScriptsFromAsset`, which is calling `CatalystInstanceImpl::jniLoadScriptFromAssets` in C++. This method when checking if bundle is a RAM bundle, uses `JniJSModulesUnbundle::isUnbundle` which only check for js-modules/UNBUNDLE - file generated when building File RAM bundle. There is no other logic to handle Indexed RAM bundle, so it figures that the bundle is not RAM, cause there is no js-modules/UNBUNDLE file and tries to load as regular bundle and fails.
In this PR we added check if it is indexed RAM bundle in `jniLoadScriptFromAssets` and handle it if it is.
## Changelog
[Android] [Fixed] fix indexed RAM bundle
Solves https://github.com/facebook/react-native/issues/21282
Pull Request resolved: https://github.com/facebook/react-native/pull/24967
Differential Revision: D15575924
Pulled By: cpojer
fbshipit-source-id: 5ea428e0b793edd8242243f39f933d1092b35260