Files
react-native/ReactCommon/cxxreact/Instance.h
T
Dratwas d8fa1206c3 fix indexed RAM bundle (#24967)
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
2019-06-03 07:14:25 -07:00

98 lines
3.4 KiB
C++

// 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.
#pragma once
#include <condition_variable>
#include <memory>
#include <cxxreact/NativeToJsBridge.h>
#ifndef RN_EXPORT
#define RN_EXPORT __attribute__((visibility("default")))
#endif
namespace folly {
struct dynamic;
}
namespace facebook {
namespace react {
class JSBigString;
class JSExecutorFactory;
class MessageQueueThread;
class ModuleRegistry;
class RAMBundleRegistry;
struct InstanceCallback {
virtual ~InstanceCallback() {}
virtual void onBatchComplete() {}
virtual void incrementPendingJSCalls() {}
virtual void decrementPendingJSCalls() {}
};
class RN_EXPORT Instance {
public:
~Instance();
void initializeBridge(std::unique_ptr<InstanceCallback> callback,
std::shared_ptr<JSExecutorFactory> jsef,
std::shared_ptr<MessageQueueThread> jsQueue,
std::shared_ptr<ModuleRegistry> moduleRegistry);
void setSourceURL(std::string sourceURL);
void loadScriptFromString(std::unique_ptr<const JSBigString> string,
std::string sourceURL, bool loadSynchronously);
static bool isIndexedRAMBundle(const char *sourcePath);
static bool isIndexedRAMBundle(std::unique_ptr<const JSBigString>* string);
void loadRAMBundleFromString(std::unique_ptr<const JSBigString> script, const std::string& sourceURL);
void loadRAMBundleFromFile(const std::string& sourcePath,
const std::string& sourceURL,
bool loadSynchronously);
void loadRAMBundle(std::unique_ptr<RAMBundleRegistry> bundleRegistry,
std::unique_ptr<const JSBigString> startupScript,
std::string startupScriptSourceURL, bool loadSynchronously);
bool supportsProfiling();
void setGlobalVariable(std::string propName,
std::unique_ptr<const JSBigString> jsonValue);
void *getJavaScriptContext();
bool isInspectable();
bool isBatchActive();
void callJSFunction(std::string &&module, std::string &&method,
folly::dynamic &&params);
void callJSCallback(uint64_t callbackId, folly::dynamic &&params);
// This method is experimental, and may be modified or removed.
void registerBundle(uint32_t bundleId, const std::string& bundlePath);
const ModuleRegistry &getModuleRegistry() const;
ModuleRegistry &getModuleRegistry();
void handleMemoryPressure(int pressureLevel);
void invokeAsync(std::function<void()>&& func);
private:
void callNativeModules(folly::dynamic &&calls, bool isEndOfBatch);
void loadApplication(std::unique_ptr<RAMBundleRegistry> bundleRegistry,
std::unique_ptr<const JSBigString> startupScript,
std::string startupScriptSourceURL);
void loadApplicationSync(std::unique_ptr<RAMBundleRegistry> bundleRegistry,
std::unique_ptr<const JSBigString> startupScript,
std::string startupScriptSourceURL);
std::shared_ptr<InstanceCallback> callback_;
std::unique_ptr<NativeToJsBridge> nativeToJsBridge_;
std::shared_ptr<ModuleRegistry> moduleRegistry_;
std::mutex m_syncMutex;
std::condition_variable m_syncCV;
bool m_syncReady = false;
};
} // namespace react
} // namespace facebook