forked from react/react-native
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathJSIExecutor.h
More file actions
140 lines (122 loc) · 4.62 KB
/
Copy pathJSIExecutor.h
File metadata and controls
140 lines (122 loc) · 4.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
* 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;
// 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_;
JSINativeModules nativeModules_;
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_;
folly::Optional<jsi::Function> callFunctionReturnResultAndFlushedQueue_;
};
using Logger =
std::function<void(const std::string &message, unsigned int logLevel)>;
void bindNativeLogger(jsi::Runtime &runtime, Logger logger);
} // namespace react
} // namespace facebook