Files
react-native/ReactCommon/jsiexecutor/jsireact/JSIExecutor.h
T
Ramanpreet Nara 0b8a82a6ee Instrument sync and async method calls (#28893)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/28893

`JSIExecutor::callSerializableNativeHook` converts the arguments from `JSI::Value` to `folly::dynamic`. Then, `RCTNativeModule` converts the arguments from `folly::dynamic` to ObjC data structures in its `static invokeInner` function.

Therefore, I decided to start the sync markers inside `JSIExecutor::callSerializableNativeHook`, which required me to expose these two methode `ModuleRegistry::getModuleName` and `ModuleRegistry::getModuleSyncMethodName`. This shouldn't modify performance because we eagerly generate a NativeModule's methods when it's first required. So, at worst, this is doing a cache lookup.

Changelog: [Internal]

Reviewed By: PeteTheHeat

Differential Revision: D21443610

fbshipit-source-id: 67cf563b0b06153e56e63ba7e186eea31eafc853
2020-05-13 20:28:18 -07:00

147 lines
4.8 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 "JSINativeModules.h"
#include <cxxreact/JSBigString.h>
#include <cxxreact/JSExecutor.h>
#include <cxxreact/RAMBundleRegistry.h>
#include <jsi/jsi.h>
#include <functional>
#include <mutex>
namespace facebook {
namespace react {
// A JSIScopedTimeoutInvoker is a trampoline-type function for introducing
// timeouts. Call the TimeoutInvoker with a function to execute, the invokee.
// The TimeoutInvoker will immediately invoke it, synchronously on the same
// thread. If the invokee fails to return after some timeout (private to the
// TimeoutInvoker), a soft error may be reported.
//
// If a soft error is reported, the second parameter errorMessageProducer will
// be invoked to produce an error message, which will be included in the soft
// error report. Note that the errorMessageProducer will be invoked
// asynchronously on a different thread.
//
// The timeout behavior does NOT cause the invokee to aborted. If the invokee
// blocks forever, so will the ScopedTimeoutInvoker (but the soft error may
// still be reported).
//
// The invokee is passed by const ref because it is executed synchronously, but
// the errorMessageProducer is passed by value because it must be copied or
// moved for async execution.
//
// Example usage:
//
// int param = ...;
// timeoutInvoker(
// [&]{ someBigWork(param); },
// [=] -> std::string {
// return "someBigWork, param " + std::to_string(param);
// })
//
using JSIScopedTimeoutInvoker = std::function<void(
const std::function<void()> &invokee,
std::function<std::string()> errorMessageProducer)>;
class BigStringBuffer : public jsi::Buffer {
public:
BigStringBuffer(std::unique_ptr<const JSBigString> script)
: script_(std::move(script)) {}
size_t size() const override {
return script_->size();
}
const uint8_t *data() const override {
return reinterpret_cast<const uint8_t *>(script_->c_str());
}
private:
std::unique_ptr<const JSBigString> script_;
};
class JSIExecutor : public JSExecutor {
public:
using RuntimeInstaller = std::function<void(jsi::Runtime &runtime)>;
JSIExecutor(
std::shared_ptr<jsi::Runtime> runtime,
std::shared_ptr<ExecutorDelegate> delegate,
const JSIScopedTimeoutInvoker &timeoutInvoker,
RuntimeInstaller runtimeInstaller);
void initializeRuntime() override;
void loadBundle(
std::unique_ptr<const JSBigString> script,
std::string sourceURL) override;
void setBundleRegistry(std::unique_ptr<RAMBundleRegistry>) override;
void registerBundle(uint32_t bundleId, const std::string &bundlePath)
override;
void callFunction(
const std::string &moduleId,
const std::string &methodId,
const folly::dynamic &arguments) override;
void invokeCallback(const double callbackId, const folly::dynamic &arguments)
override;
void setGlobalVariable(
std::string propName,
std::unique_ptr<const JSBigString> jsonValue) override;
std::string getDescription() override;
void *getJavaScriptContext() override;
bool isInspectable() override;
void handleMemoryPressure(int pressureLevel) override;
// An implementation of JSIScopedTimeoutInvoker that simply runs the
// invokee, with no timeout.
static void defaultTimeoutInvoker(
const std::function<void()> &invokee,
std::function<std::string()> errorMessageProducer) {
(void)errorMessageProducer;
invokee();
}
void flush() override;
private:
class NativeModuleProxy;
void bindBridge();
void callNativeModules(const jsi::Value &queue, bool isEndOfBatch);
jsi::Value nativeCallSyncHook(const jsi::Value *args, size_t count);
jsi::Value nativeRequire(const jsi::Value *args, size_t count);
#ifdef DEBUG
jsi::Value globalEvalWithSourceUrl(const jsi::Value *args, size_t count);
#endif
std::shared_ptr<jsi::Runtime> runtime_;
std::shared_ptr<ExecutorDelegate> delegate_;
std::shared_ptr<JSINativeModules> nativeModules_;
std::shared_ptr<ModuleRegistry> moduleRegistry_;
std::once_flag bindFlag_;
std::unique_ptr<RAMBundleRegistry> bundleRegistry_;
JSIScopedTimeoutInvoker scopedTimeoutInvoker_;
RuntimeInstaller runtimeInstaller_;
folly::Optional<jsi::Function> callFunctionReturnFlushedQueue_;
folly::Optional<jsi::Function> invokeCallbackAndReturnFlushedQueue_;
folly::Optional<jsi::Function> flushedQueue_;
};
using Logger =
std::function<void(const std::string &message, unsigned int logLevel)>;
void bindNativeLogger(jsi::Runtime &runtime, Logger logger);
using PerformanceNow = std::function<double()>;
void bindNativePerformanceNow(
jsi::Runtime &runtime,
PerformanceNow performanceNow);
} // namespace react
} // namespace facebook