@onekeyfe/react-native-background-thread 1.1.46 → 1.1.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/BackgroundThread.podspec +4 -2
  2. package/android/CMakeLists.txt +29 -0
  3. package/android/build.gradle +42 -0
  4. package/android/src/main/cpp/cpp-adapter.cpp +222 -0
  5. package/android/src/main/java/com/backgroundthread/BTLogger.kt +55 -0
  6. package/android/src/main/java/com/backgroundthread/BackgroundThreadManager.kt +258 -0
  7. package/android/src/main/java/com/backgroundthread/BackgroundThreadModule.kt +17 -17
  8. package/cpp/SharedRPC.cpp +223 -0
  9. package/cpp/SharedRPC.h +50 -0
  10. package/cpp/SharedStore.cpp +184 -0
  11. package/cpp/SharedStore.h +28 -0
  12. package/ios/BackgroundRunnerReactNativeDelegate.h +0 -17
  13. package/ios/BackgroundRunnerReactNativeDelegate.mm +83 -123
  14. package/ios/BackgroundThread.h +1 -0
  15. package/ios/BackgroundThread.mm +6 -22
  16. package/ios/BackgroundThreadManager.h +6 -12
  17. package/ios/BackgroundThreadManager.mm +39 -30
  18. package/lib/module/NativeBackgroundThread.js.map +1 -1
  19. package/lib/module/SharedRPC.js +6 -0
  20. package/lib/module/SharedRPC.js.map +1 -0
  21. package/lib/module/SharedStore.js +6 -0
  22. package/lib/module/SharedStore.js.map +1 -0
  23. package/lib/module/index.js +2 -0
  24. package/lib/module/index.js.map +1 -1
  25. package/lib/typescript/src/NativeBackgroundThread.d.ts +2 -4
  26. package/lib/typescript/src/NativeBackgroundThread.d.ts.map +1 -1
  27. package/lib/typescript/src/SharedRPC.d.ts +12 -0
  28. package/lib/typescript/src/SharedRPC.d.ts.map +1 -0
  29. package/lib/typescript/src/SharedStore.d.ts +14 -0
  30. package/lib/typescript/src/SharedStore.d.ts.map +1 -0
  31. package/lib/typescript/src/index.d.ts +4 -0
  32. package/lib/typescript/src/index.d.ts.map +1 -1
  33. package/package.json +2 -2
  34. package/src/NativeBackgroundThread.ts +2 -4
  35. package/src/SharedRPC.ts +16 -0
  36. package/src/SharedStore.ts +18 -0
  37. package/src/index.tsx +4 -0
@@ -0,0 +1,223 @@
1
+ #include "SharedRPC.h"
2
+
3
+ #ifdef __ANDROID__
4
+ #include <android/log.h>
5
+ #define RPC_LOG(...) __android_log_print(ANDROID_LOG_INFO, "SharedRPC", __VA_ARGS__)
6
+ #else
7
+ #define RPC_LOG(...)
8
+ #endif
9
+
10
+ std::mutex SharedRPC::mutex_;
11
+ std::unordered_map<std::string, RPCValue> SharedRPC::slots_;
12
+ std::vector<RuntimeListener> SharedRPC::listeners_;
13
+
14
+ void SharedRPC::install(jsi::Runtime &rt) {
15
+ auto rpc = std::make_shared<SharedRPC>();
16
+ auto obj = jsi::Object::createFromHostObject(rt, rpc);
17
+ rt.global().setProperty(rt, "sharedRPC", std::move(obj));
18
+ }
19
+
20
+ void SharedRPC::install(jsi::Runtime &rt, RPCRuntimeExecutor executor,
21
+ const std::string &runtimeId) {
22
+ auto rpc = std::make_shared<SharedRPC>();
23
+ auto obj = jsi::Object::createFromHostObject(rt, rpc);
24
+ rt.global().setProperty(rt, "sharedRPC", std::move(obj));
25
+
26
+ std::lock_guard<std::mutex> lock(mutex_);
27
+ // Remove any existing listener with the same runtimeId (reload scenario).
28
+ // IMPORTANT: The old listener's callback is a jsi::Function tied to the old
29
+ // runtime. On reload, that runtime is already destroyed, so calling
30
+ // ~jsi::Function() would crash (null deref in Pointer::~Pointer).
31
+ // We intentionally leak the callback to avoid this.
32
+ for (auto &listener : listeners_) {
33
+ if (listener.runtimeId == runtimeId && listener.callback) {
34
+ new std::shared_ptr<jsi::Function>(std::move(listener.callback));
35
+ }
36
+ }
37
+ listeners_.erase(
38
+ std::remove_if(listeners_.begin(), listeners_.end(),
39
+ [&runtimeId](const RuntimeListener &l) {
40
+ return l.runtimeId == runtimeId;
41
+ }),
42
+ listeners_.end());
43
+ listeners_.push_back({runtimeId, &rt, std::move(executor), nullptr});
44
+ }
45
+
46
+ void SharedRPC::reset() {
47
+ std::lock_guard<std::mutex> lock(mutex_);
48
+ slots_.clear();
49
+ listeners_.clear();
50
+ }
51
+
52
+ void SharedRPC::notifyOtherRuntime(jsi::Runtime &callerRt, const std::string &callId) {
53
+ // Collect executors and callbacks under lock, then invoke outside lock
54
+ // to avoid deadlock (executor may schedule work that also acquires mutex_).
55
+ std::vector<std::pair<RPCRuntimeExecutor, std::shared_ptr<jsi::Function>>> toNotify;
56
+ {
57
+ std::lock_guard<std::mutex> lock(mutex_);
58
+ RPC_LOG("notifyOtherRuntime: callId=%s, listeners=%zu, callerRt=%p",
59
+ callId.c_str(), listeners_.size(), &callerRt);
60
+ for (auto &listener : listeners_) {
61
+ RPC_LOG(" listener: id=%s, rt=%p, hasCallback=%d",
62
+ listener.runtimeId.c_str(), listener.runtime, listener.callback != nullptr);
63
+ if (listener.runtime == &callerRt) continue;
64
+ if (!listener.callback) continue;
65
+ toNotify.emplace_back(listener.executor, listener.callback);
66
+ }
67
+ RPC_LOG(" toNotify count: %zu", toNotify.size());
68
+ }
69
+
70
+ for (auto &[executor, cb] : toNotify) {
71
+ auto id = callId;
72
+ RPC_LOG(" invoking executor for callId=%s", id.c_str());
73
+ executor([cb, id](jsi::Runtime &rt) {
74
+ RPC_LOG(" executor work running for callId=%s", id.c_str());
75
+ try {
76
+ cb->call(rt, jsi::String::createFromUtf8(rt, id));
77
+ RPC_LOG(" cb->call succeeded for callId=%s", id.c_str());
78
+ } catch (const jsi::JSError &e) {
79
+ RPC_LOG(" JSError in cb->call: %s", e.getMessage().c_str());
80
+ } catch (...) {
81
+ RPC_LOG(" Unknown error in cb->call");
82
+ }
83
+ });
84
+ }
85
+ }
86
+
87
+ RPCValue SharedRPC::extractValue(jsi::Runtime &rt, const jsi::Value &val) {
88
+ if (val.isBool()) {
89
+ return val.getBool();
90
+ }
91
+ if (val.isNumber()) {
92
+ return val.getNumber();
93
+ }
94
+ if (val.isString()) {
95
+ return val.getString(rt).utf8(rt);
96
+ }
97
+ throw jsi::JSError(rt,
98
+ "SharedRPC: unsupported value type. "
99
+ "Only bool, number, and string are supported.");
100
+ }
101
+
102
+ jsi::Value SharedRPC::toJSI(jsi::Runtime &rt, const RPCValue &val) {
103
+ if (std::holds_alternative<bool>(val)) {
104
+ return jsi::Value(std::get<bool>(val));
105
+ }
106
+ if (std::holds_alternative<double>(val)) {
107
+ return jsi::Value(std::get<double>(val));
108
+ }
109
+ // std::string
110
+ return jsi::String::createFromUtf8(rt, std::get<std::string>(val));
111
+ }
112
+
113
+ jsi::Value SharedRPC::get(jsi::Runtime &rt, const jsi::PropNameID &name) {
114
+ auto prop = name.utf8(rt);
115
+
116
+ // write(callId: string, value: bool | number | string): void
117
+ if (prop == "write") {
118
+ return jsi::Function::createFromHostFunction(
119
+ rt, name, 2,
120
+ [this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *args,
121
+ size_t count) -> jsi::Value {
122
+ if (count < 2 || !args[0].isString()) {
123
+ throw jsi::JSError(
124
+ rt, "SharedRPC.write expects (callId: string, value)");
125
+ }
126
+ auto callId = args[0].getString(rt).utf8(rt);
127
+ auto value = extractValue(rt, args[1]);
128
+ {
129
+ std::lock_guard<std::mutex> lock(mutex_);
130
+ slots_.insert_or_assign(callId, std::move(value));
131
+ }
132
+ // Notify OUTSIDE the lock
133
+ notifyOtherRuntime(rt, callId);
134
+ return jsi::Value::undefined();
135
+ });
136
+ }
137
+
138
+ // read(callId: string): bool | number | string | undefined
139
+ // Deletes the entry after reading (read-and-delete semantics).
140
+ if (prop == "read") {
141
+ return jsi::Function::createFromHostFunction(
142
+ rt, name, 1,
143
+ [](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *args,
144
+ size_t count) -> jsi::Value {
145
+ if (count < 1 || !args[0].isString()) {
146
+ throw jsi::JSError(
147
+ rt, "SharedRPC.read expects (callId: string)");
148
+ }
149
+ auto callId = args[0].getString(rt).utf8(rt);
150
+ {
151
+ std::lock_guard<std::mutex> lock(mutex_);
152
+ auto it = slots_.find(callId);
153
+ if (it == slots_.end()) {
154
+ return jsi::Value::undefined();
155
+ }
156
+ auto value = std::move(it->second);
157
+ slots_.erase(it);
158
+ return toJSI(rt, value);
159
+ }
160
+ });
161
+ }
162
+
163
+ // has(callId: string): boolean
164
+ if (prop == "has") {
165
+ return jsi::Function::createFromHostFunction(
166
+ rt, name, 1,
167
+ [](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *args,
168
+ size_t count) -> jsi::Value {
169
+ if (count < 1 || !args[0].isString()) {
170
+ throw jsi::JSError(
171
+ rt, "SharedRPC.has expects (callId: string)");
172
+ }
173
+ auto callId = args[0].getString(rt).utf8(rt);
174
+ {
175
+ std::lock_guard<std::mutex> lock(mutex_);
176
+ return jsi::Value(slots_.count(callId) > 0);
177
+ }
178
+ });
179
+ }
180
+
181
+ // pendingCount: number (getter, not a function)
182
+ if (prop == "pendingCount") {
183
+ std::lock_guard<std::mutex> lock(mutex_);
184
+ return jsi::Value(static_cast<double>(slots_.size()));
185
+ }
186
+
187
+ // onWrite(callback: (callId: string) => void): void
188
+ if (prop == "onWrite") {
189
+ return jsi::Function::createFromHostFunction(
190
+ rt, name, 1,
191
+ [](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *args,
192
+ size_t count) -> jsi::Value {
193
+ if (count < 1 || !args[0].isObject() ||
194
+ !args[0].asObject(rt).isFunction(rt)) {
195
+ throw jsi::JSError(rt, "SharedRPC.onWrite expects a function");
196
+ }
197
+ auto fn = std::make_shared<jsi::Function>(
198
+ args[0].asObject(rt).asFunction(rt));
199
+ {
200
+ std::lock_guard<std::mutex> lock(mutex_);
201
+ for (auto &listener : listeners_) {
202
+ if (listener.runtime == &rt) {
203
+ listener.callback = std::move(fn);
204
+ break;
205
+ }
206
+ }
207
+ }
208
+ return jsi::Value::undefined();
209
+ });
210
+ }
211
+
212
+ return jsi::Value::undefined();
213
+ }
214
+
215
+ std::vector<jsi::PropNameID> SharedRPC::getPropertyNames(jsi::Runtime &rt) {
216
+ std::vector<jsi::PropNameID> props;
217
+ props.push_back(jsi::PropNameID::forUtf8(rt, "write"));
218
+ props.push_back(jsi::PropNameID::forUtf8(rt, "read"));
219
+ props.push_back(jsi::PropNameID::forUtf8(rt, "has"));
220
+ props.push_back(jsi::PropNameID::forUtf8(rt, "pendingCount"));
221
+ props.push_back(jsi::PropNameID::forUtf8(rt, "onWrite"));
222
+ return props;
223
+ }
@@ -0,0 +1,50 @@
1
+ #pragma once
2
+
3
+ #include <jsi/jsi.h>
4
+ #include <functional>
5
+ #include <memory>
6
+ #include <mutex>
7
+ #include <string>
8
+ #include <unordered_map>
9
+ #include <variant>
10
+ #include <vector>
11
+
12
+ namespace jsi = facebook::jsi;
13
+
14
+ using RPCValue = std::variant<bool, double, std::string>;
15
+
16
+ // Executes a callback on a specific runtime's JS thread.
17
+ // The implementation is platform-specific (iOS vs Android).
18
+ using RPCRuntimeExecutor = std::function<void(std::function<void(jsi::Runtime &)>)>;
19
+
20
+ struct RuntimeListener {
21
+ std::string runtimeId; // "main" or "background"
22
+ jsi::Runtime *runtime;
23
+ RPCRuntimeExecutor executor;
24
+ std::shared_ptr<jsi::Function> callback; // JS onWrite callback
25
+ };
26
+
27
+ class SharedRPC : public jsi::HostObject {
28
+ public:
29
+ jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &name) override;
30
+ std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
31
+
32
+ /// Legacy install without executor (no cross-runtime notification)
33
+ static void install(jsi::Runtime &rt);
34
+
35
+ /// Install with executor — enables cross-runtime write notifications
36
+ /// runtimeId should be "main" or "background" — used for dedup on reload.
37
+ static void install(jsi::Runtime &rt, RPCRuntimeExecutor executor,
38
+ const std::string &runtimeId);
39
+
40
+ static void reset();
41
+
42
+ private:
43
+ static RPCValue extractValue(jsi::Runtime &rt, const jsi::Value &val);
44
+ static jsi::Value toJSI(jsi::Runtime &rt, const RPCValue &val);
45
+ void notifyOtherRuntime(jsi::Runtime &callerRt, const std::string &callId);
46
+
47
+ static std::mutex mutex_;
48
+ static std::unordered_map<std::string, RPCValue> slots_;
49
+ static std::vector<RuntimeListener> listeners_;
50
+ };
@@ -0,0 +1,184 @@
1
+ #include "SharedStore.h"
2
+
3
+ // Static member definitions
4
+ std::mutex SharedStore::mutex_;
5
+ std::unordered_map<std::string, StoreValue> SharedStore::data_;
6
+
7
+ void SharedStore::install(jsi::Runtime &rt) {
8
+ auto store = std::make_shared<SharedStore>();
9
+ auto obj = jsi::Object::createFromHostObject(rt, store);
10
+ rt.global().setProperty(rt, "sharedStore", std::move(obj));
11
+ }
12
+
13
+ void SharedStore::reset() {
14
+ std::lock_guard<std::mutex> lock(mutex_);
15
+ data_.clear();
16
+ }
17
+
18
+ StoreValue SharedStore::extractValue(jsi::Runtime &rt,
19
+ const jsi::Value &val) {
20
+ if (val.isBool()) {
21
+ return val.getBool();
22
+ }
23
+ if (val.isNumber()) {
24
+ return val.getNumber();
25
+ }
26
+ if (val.isString()) {
27
+ return val.getString(rt).utf8(rt);
28
+ }
29
+ throw jsi::JSError(rt,
30
+ "SharedStore: unsupported value type. "
31
+ "Only bool, number, and string are supported.");
32
+ }
33
+
34
+ jsi::Value SharedStore::toJSI(jsi::Runtime &rt, const StoreValue &val) {
35
+ if (std::holds_alternative<bool>(val)) {
36
+ return jsi::Value(std::get<bool>(val));
37
+ }
38
+ if (std::holds_alternative<double>(val)) {
39
+ return jsi::Value(std::get<double>(val));
40
+ }
41
+ if (std::holds_alternative<std::string>(val)) {
42
+ return jsi::String::createFromUtf8(rt, std::get<std::string>(val));
43
+ }
44
+ return jsi::Value::undefined();
45
+ }
46
+
47
+ jsi::Value SharedStore::get(jsi::Runtime &rt, const jsi::PropNameID &name) {
48
+ auto prop = name.utf8(rt);
49
+
50
+ // set(key: string, value: bool | number | string): void
51
+ if (prop == "set") {
52
+ return jsi::Function::createFromHostFunction(
53
+ rt, name, 2,
54
+ [](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *args,
55
+ size_t count) -> jsi::Value {
56
+ if (count < 2 || !args[0].isString()) {
57
+ throw jsi::JSError(
58
+ rt, "SharedStore.set expects (string key, value)");
59
+ }
60
+ auto key = args[0].getString(rt).utf8(rt);
61
+ auto val = extractValue(rt, args[1]);
62
+ {
63
+ std::lock_guard<std::mutex> lock(mutex_);
64
+ data_[std::move(key)] = std::move(val);
65
+ }
66
+ return jsi::Value::undefined();
67
+ });
68
+ }
69
+
70
+ // get(key: string): bool | number | string | undefined
71
+ if (prop == "get") {
72
+ return jsi::Function::createFromHostFunction(
73
+ rt, name, 1,
74
+ [](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *args,
75
+ size_t count) -> jsi::Value {
76
+ if (count < 1 || !args[0].isString()) {
77
+ throw jsi::JSError(
78
+ rt, "SharedStore.get expects a string key");
79
+ }
80
+ auto key = args[0].getString(rt).utf8(rt);
81
+ {
82
+ std::lock_guard<std::mutex> lock(mutex_);
83
+ auto it = data_.find(key);
84
+ if (it == data_.end()) {
85
+ return jsi::Value::undefined();
86
+ }
87
+ return toJSI(rt, it->second);
88
+ }
89
+ });
90
+ }
91
+
92
+ // has(key: string): boolean
93
+ if (prop == "has") {
94
+ return jsi::Function::createFromHostFunction(
95
+ rt, name, 1,
96
+ [](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *args,
97
+ size_t count) -> jsi::Value {
98
+ if (count < 1 || !args[0].isString()) {
99
+ throw jsi::JSError(
100
+ rt, "SharedStore.has expects a string key");
101
+ }
102
+ auto key = args[0].getString(rt).utf8(rt);
103
+ {
104
+ std::lock_guard<std::mutex> lock(mutex_);
105
+ return jsi::Value(data_.count(key) > 0);
106
+ }
107
+ });
108
+ }
109
+
110
+ // delete(key: string): boolean
111
+ if (prop == "delete") {
112
+ return jsi::Function::createFromHostFunction(
113
+ rt, name, 1,
114
+ [](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *args,
115
+ size_t count) -> jsi::Value {
116
+ if (count < 1 || !args[0].isString()) {
117
+ throw jsi::JSError(
118
+ rt, "SharedStore.delete expects a string key");
119
+ }
120
+ auto key = args[0].getString(rt).utf8(rt);
121
+ {
122
+ std::lock_guard<std::mutex> lock(mutex_);
123
+ return jsi::Value(data_.erase(key) > 0);
124
+ }
125
+ });
126
+ }
127
+
128
+ // keys(): string[]
129
+ if (prop == "keys") {
130
+ return jsi::Function::createFromHostFunction(
131
+ rt, name, 0,
132
+ [](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *,
133
+ size_t) -> jsi::Value {
134
+ std::vector<std::string> allKeys;
135
+ {
136
+ std::lock_guard<std::mutex> lock(mutex_);
137
+ allKeys.reserve(data_.size());
138
+ for (const auto &pair : data_) {
139
+ allKeys.push_back(pair.first);
140
+ }
141
+ }
142
+ auto arr = jsi::Array(rt, allKeys.size());
143
+ for (size_t i = 0; i < allKeys.size(); i++) {
144
+ arr.setValueAtIndex(
145
+ rt, i, jsi::String::createFromUtf8(rt, allKeys[i]));
146
+ }
147
+ return arr;
148
+ });
149
+ }
150
+
151
+ // clear(): void
152
+ if (prop == "clear") {
153
+ return jsi::Function::createFromHostFunction(
154
+ rt, name, 0,
155
+ [](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *,
156
+ size_t) -> jsi::Value {
157
+ {
158
+ std::lock_guard<std::mutex> lock(mutex_);
159
+ data_.clear();
160
+ }
161
+ return jsi::Value::undefined();
162
+ });
163
+ }
164
+
165
+ // size: number (getter, not a function)
166
+ if (prop == "size") {
167
+ std::lock_guard<std::mutex> lock(mutex_);
168
+ return jsi::Value(static_cast<double>(data_.size()));
169
+ }
170
+
171
+ return jsi::Value::undefined();
172
+ }
173
+
174
+ std::vector<jsi::PropNameID> SharedStore::getPropertyNames(jsi::Runtime &rt) {
175
+ std::vector<jsi::PropNameID> props;
176
+ props.push_back(jsi::PropNameID::forUtf8(rt, "set"));
177
+ props.push_back(jsi::PropNameID::forUtf8(rt, "get"));
178
+ props.push_back(jsi::PropNameID::forUtf8(rt, "has"));
179
+ props.push_back(jsi::PropNameID::forUtf8(rt, "delete"));
180
+ props.push_back(jsi::PropNameID::forUtf8(rt, "keys"));
181
+ props.push_back(jsi::PropNameID::forUtf8(rt, "clear"));
182
+ props.push_back(jsi::PropNameID::forUtf8(rt, "size"));
183
+ return props;
184
+ }
@@ -0,0 +1,28 @@
1
+ #pragma once
2
+
3
+ #include <jsi/jsi.h>
4
+ #include <mutex>
5
+ #include <string>
6
+ #include <unordered_map>
7
+ #include <variant>
8
+ #include <vector>
9
+
10
+ namespace jsi = facebook::jsi;
11
+
12
+ using StoreValue = std::variant<bool, double, std::string>;
13
+
14
+ class SharedStore : public jsi::HostObject {
15
+ public:
16
+ jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &name) override;
17
+ std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
18
+
19
+ static void install(jsi::Runtime &rt);
20
+ static void reset();
21
+
22
+ private:
23
+ static StoreValue extractValue(jsi::Runtime &rt, const jsi::Value &val);
24
+ static jsi::Value toJSI(jsi::Runtime &rt, const StoreValue &val);
25
+
26
+ static std::mutex mutex_;
27
+ static std::unordered_map<std::string, StoreValue> data_;
28
+ };
@@ -18,7 +18,6 @@ NS_ASSUME_NONNULL_BEGIN
18
18
 
19
19
  @interface BackgroundReactNativeDelegate : RCTDefaultReactNativeFactoryDelegate
20
20
 
21
- //@property (nonatomic) std::shared_ptr<const facebook::react::SandboxReactNativeViewEventEmitter> eventEmitter;
22
21
  @property (nonatomic, assign) BOOL hasOnMessageHandler;
23
22
  @property (nonatomic, assign) BOOL hasOnErrorHandler;
24
23
 
@@ -26,28 +25,12 @@ NS_ASSUME_NONNULL_BEGIN
26
25
 
27
26
  @property (nonatomic, readwrite) std::string origin;
28
27
 
29
- @property (nonatomic, copy) void (^onMessageCallback)(NSString *message);
30
-
31
28
  /**
32
29
  * Initializes the delegate.
33
30
  * @return Initialized delegate instance with filtered module access
34
31
  */
35
32
  - (instancetype)init;
36
33
 
37
- /**
38
- * Posts a message to the JavaScript runtime.
39
- * @param message C++ string containing the JSON.stringified message
40
- */
41
- - (void)postMessage:(const std::string &)message;
42
-
43
- /**
44
- * Routes a message to a specific sandbox delegate.
45
- * @param message The message to route
46
- * @param targetId The ID of the target sandbox
47
- * @return true if the message was successfully routed, false otherwise
48
- */
49
- - (bool)routeMessage:(const std::string &)message toSandbox:(const std::string &)targetId;
50
-
51
34
  @end
52
35
 
53
36
  NS_ASSUME_NONNULL_END