@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.
- package/BackgroundThread.podspec +4 -2
- package/android/CMakeLists.txt +29 -0
- package/android/build.gradle +42 -0
- package/android/src/main/cpp/cpp-adapter.cpp +222 -0
- package/android/src/main/java/com/backgroundthread/BTLogger.kt +55 -0
- package/android/src/main/java/com/backgroundthread/BackgroundThreadManager.kt +258 -0
- package/android/src/main/java/com/backgroundthread/BackgroundThreadModule.kt +17 -17
- package/cpp/SharedRPC.cpp +223 -0
- package/cpp/SharedRPC.h +50 -0
- package/cpp/SharedStore.cpp +184 -0
- package/cpp/SharedStore.h +28 -0
- package/ios/BackgroundRunnerReactNativeDelegate.h +0 -17
- package/ios/BackgroundRunnerReactNativeDelegate.mm +83 -123
- package/ios/BackgroundThread.h +1 -0
- package/ios/BackgroundThread.mm +6 -22
- package/ios/BackgroundThreadManager.h +6 -12
- package/ios/BackgroundThreadManager.mm +39 -30
- package/lib/module/NativeBackgroundThread.js.map +1 -1
- package/lib/module/SharedRPC.js +6 -0
- package/lib/module/SharedRPC.js.map +1 -0
- package/lib/module/SharedStore.js +6 -0
- package/lib/module/SharedStore.js.map +1 -0
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/NativeBackgroundThread.d.ts +2 -4
- package/lib/typescript/src/NativeBackgroundThread.d.ts.map +1 -1
- package/lib/typescript/src/SharedRPC.d.ts +12 -0
- package/lib/typescript/src/SharedRPC.d.ts.map +1 -0
- package/lib/typescript/src/SharedStore.d.ts +14 -0
- package/lib/typescript/src/SharedStore.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +4 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/NativeBackgroundThread.ts +2 -4
- package/src/SharedRPC.ts +16 -0
- package/src/SharedStore.ts +18 -0
- package/src/index.tsx +4 -0
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
#include <memory>
|
|
9
9
|
#include <mutex>
|
|
10
10
|
|
|
11
|
+
#include "SharedStore.h"
|
|
12
|
+
#include "SharedRPC.h"
|
|
13
|
+
|
|
11
14
|
#import <React/RCTBridge.h>
|
|
12
15
|
#import <React/RCTBundleURLProvider.h>
|
|
13
16
|
|
|
@@ -51,26 +54,75 @@ static void stubJsiFunction(jsi::Runtime &runtime, jsi::Object &object, const ch
|
|
|
51
54
|
}));
|
|
52
55
|
}
|
|
53
56
|
|
|
54
|
-
static
|
|
57
|
+
static void invokeOptionalGlobalFunction(jsi::Runtime &runtime, const char *name)
|
|
58
|
+
{
|
|
59
|
+
try {
|
|
60
|
+
jsi::Value fnValue = runtime.global().getProperty(runtime, name);
|
|
61
|
+
if (!fnValue.isObject() || !fnValue.asObject(runtime).isFunction(runtime)) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
jsi::Function fn = fnValue.asObject(runtime).asFunction(runtime);
|
|
66
|
+
fn.call(runtime);
|
|
67
|
+
} catch (const jsi::JSError &e) {
|
|
68
|
+
[BTLogger error:[NSString stringWithFormat:@"JSError calling global function %s: %s", name, e.getMessage().c_str()]];
|
|
69
|
+
} catch (const std::exception &e) {
|
|
70
|
+
[BTLogger error:[NSString stringWithFormat:@"Error calling global function %s: %s", name, e.what()]];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
static NSURL *resolveMainBundleResourceURL(NSString *resourceName)
|
|
55
75
|
{
|
|
56
|
-
if (
|
|
57
|
-
return
|
|
76
|
+
if (resourceName.length == 0) {
|
|
77
|
+
return nil;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
NSURL *directURL = [[NSBundle mainBundle] URLForResource:resourceName withExtension:nil];
|
|
81
|
+
if (directURL) {
|
|
82
|
+
return directURL;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
NSString *normalizedName = [resourceName hasPrefix:@"/"]
|
|
86
|
+
? resourceName.lastPathComponent
|
|
87
|
+
: resourceName;
|
|
88
|
+
NSString *extension = normalizedName.pathExtension;
|
|
89
|
+
NSString *baseName = normalizedName.stringByDeletingPathExtension;
|
|
90
|
+
if (baseName.length == 0) {
|
|
91
|
+
return nil;
|
|
58
92
|
}
|
|
59
|
-
|
|
60
|
-
return
|
|
93
|
+
|
|
94
|
+
return [[NSBundle mainBundle] URLForResource:baseName
|
|
95
|
+
withExtension:extension.length > 0 ? extension : nil];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
static NSURL *resolveBundleSourceURL(NSString *jsBundleSourceNS)
|
|
99
|
+
{
|
|
100
|
+
if (jsBundleSourceNS.length == 0) {
|
|
101
|
+
return nil;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
NSURL *parsedURL = [NSURL URLWithString:jsBundleSourceNS];
|
|
105
|
+
if (parsedURL.scheme.length > 0) {
|
|
106
|
+
if (parsedURL.isFileURL && parsedURL.path.length > 0) {
|
|
107
|
+
return [NSURL fileURLWithPath:parsedURL.path];
|
|
108
|
+
}
|
|
109
|
+
return parsedURL;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if ([jsBundleSourceNS hasPrefix:@"/"]) {
|
|
113
|
+
return [NSURL fileURLWithPath:jsBundleSourceNS];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return resolveMainBundleResourceURL(jsBundleSourceNS);
|
|
61
117
|
}
|
|
62
118
|
|
|
63
119
|
@interface BackgroundReactNativeDelegate () {
|
|
64
120
|
RCTInstance *_rctInstance;
|
|
65
|
-
std::shared_ptr<jsi::Function> _onMessageSandbox;
|
|
66
121
|
std::string _origin;
|
|
67
122
|
std::string _jsBundleSource;
|
|
68
123
|
}
|
|
69
124
|
|
|
70
125
|
- (void)cleanupResources;
|
|
71
|
-
|
|
72
|
-
- (jsi::Function)createPostMessageFunction:(jsi::Runtime &)runtime;
|
|
73
|
-
- (jsi::Function)createSetOnMessageFunction:(jsi::Runtime &)runtime;
|
|
74
126
|
- (void)setupErrorHandler:(jsi::Runtime &)runtime;
|
|
75
127
|
|
|
76
128
|
@end
|
|
@@ -91,7 +143,6 @@ static std::string safeGetStringProperty(jsi::Runtime &rt, const jsi::Object &ob
|
|
|
91
143
|
|
|
92
144
|
- (void)cleanupResources
|
|
93
145
|
{
|
|
94
|
-
_onMessageSandbox.reset();
|
|
95
146
|
_rctInstance = nil;
|
|
96
147
|
}
|
|
97
148
|
|
|
@@ -121,56 +172,19 @@ static std::string safeGetStringProperty(jsi::Runtime &rt, const jsi::Object &ob
|
|
|
121
172
|
{
|
|
122
173
|
if (!_jsBundleSource.empty()) {
|
|
123
174
|
NSString *jsBundleSourceNS = [NSString stringWithUTF8String:_jsBundleSource.c_str()];
|
|
124
|
-
NSURL *
|
|
125
|
-
if (
|
|
126
|
-
return
|
|
175
|
+
NSURL *resolvedURL = resolveBundleSourceURL(jsBundleSourceNS);
|
|
176
|
+
if (resolvedURL) {
|
|
177
|
+
return resolvedURL;
|
|
127
178
|
}
|
|
128
179
|
|
|
129
|
-
|
|
130
|
-
return [[NSBundle mainBundle] URLForResource:jsBundleSourceNS withExtension:nil];
|
|
131
|
-
}
|
|
180
|
+
[BTLogger warn:[NSString stringWithFormat:@"Unable to resolve custom jsBundleSource=%@", jsBundleSourceNS]];
|
|
132
181
|
}
|
|
133
182
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
- (void)postMessage:(const std::string &)message
|
|
138
|
-
{
|
|
139
|
-
if (!_onMessageSandbox || !_rctInstance) {
|
|
140
|
-
return;
|
|
183
|
+
NSURL *defaultBundleURL = resolveMainBundleResourceURL(@"background.bundle");
|
|
184
|
+
if (defaultBundleURL) {
|
|
185
|
+
return defaultBundleURL;
|
|
141
186
|
}
|
|
142
|
-
|
|
143
|
-
[_rctInstance callFunctionOnBufferedRuntimeExecutor:[=](jsi::Runtime &runtime) {
|
|
144
|
-
try {
|
|
145
|
-
// Validate runtime before any JSI operations
|
|
146
|
-
runtime.global(); // Test if runtime is accessible
|
|
147
|
-
|
|
148
|
-
// Double-check the JSI function is still valid
|
|
149
|
-
if (!_onMessageSandbox) {
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
jsi::Value parsedValue = runtime.global()
|
|
154
|
-
.getPropertyAsObject(runtime, "JSON")
|
|
155
|
-
.getPropertyAsFunction(runtime, "parse")
|
|
156
|
-
.call(runtime, jsi::String::createFromUtf8(runtime, message));
|
|
157
|
-
|
|
158
|
-
_onMessageSandbox->call(runtime, {std::move(parsedValue)});
|
|
159
|
-
} catch (const jsi::JSError &e) {
|
|
160
|
-
[BTLogger error:[NSString stringWithFormat:@"JSError during postMessage: %s", e.getMessage().c_str()]];
|
|
161
|
-
} catch (const std::exception &e) {
|
|
162
|
-
[BTLogger error:[NSString stringWithFormat:@"RuntimeError during postMessage: %s", e.what()]];
|
|
163
|
-
} catch (...) {
|
|
164
|
-
[BTLogger error:[NSString stringWithFormat:@"Runtime invalid during postMessage for sandbox %s", _origin.c_str()]];
|
|
165
|
-
}
|
|
166
|
-
}];
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
- (bool)routeMessage:(const std::string &)message toSandbox:(const std::string &)targetId
|
|
170
|
-
{
|
|
171
|
-
// Sandbox routing is not yet implemented. Deny all cross-sandbox messages by default.
|
|
172
|
-
[BTLogger warn:@"routeMessage denied: sandbox routing not implemented"];
|
|
173
|
-
return false;
|
|
187
|
+
return [[NSBundle mainBundle] URLForResource:@"background" withExtension:@"bundle"];
|
|
174
188
|
}
|
|
175
189
|
|
|
176
190
|
- (void)hostDidStart:(RCTHost *)host
|
|
@@ -179,11 +193,6 @@ static std::string safeGetStringProperty(jsi::Runtime &rt, const jsi::Object &ob
|
|
|
179
193
|
return;
|
|
180
194
|
}
|
|
181
195
|
|
|
182
|
-
// Safely clear any existing JSI function and instance before new runtime setup
|
|
183
|
-
// This prevents crash on reload when old function is tied to invalid runtime
|
|
184
|
-
_onMessageSandbox.reset();
|
|
185
|
-
_onMessageSandbox = nullptr;
|
|
186
|
-
|
|
187
196
|
// Clear old instance reference before setting new one
|
|
188
197
|
_rctInstance = nil;
|
|
189
198
|
|
|
@@ -195,9 +204,21 @@ static std::string safeGetStringProperty(jsi::Runtime &rt, const jsi::Object &ob
|
|
|
195
204
|
}
|
|
196
205
|
|
|
197
206
|
[_rctInstance callFunctionOnBufferedRuntimeExecutor:[=](jsi::Runtime &runtime) {
|
|
198
|
-
facebook::react::defineReadOnlyGlobal(runtime, "postHostMessage", [self createPostMessageFunction:runtime]);
|
|
199
|
-
facebook::react::defineReadOnlyGlobal(runtime, "onHostMessage", [self createSetOnMessageFunction:runtime]);
|
|
200
207
|
[self setupErrorHandler:runtime];
|
|
208
|
+
|
|
209
|
+
// Install SharedStore into background runtime
|
|
210
|
+
SharedStore::install(runtime);
|
|
211
|
+
|
|
212
|
+
// Install SharedRPC with executor for cross-runtime notifications
|
|
213
|
+
RCTInstance *bgInstance = _rctInstance;
|
|
214
|
+
RPCRuntimeExecutor bgExecutor = [bgInstance](std::function<void(jsi::Runtime &)> work) {
|
|
215
|
+
[bgInstance callFunctionOnBufferedRuntimeExecutor:[work](jsi::Runtime &rt) {
|
|
216
|
+
work(rt);
|
|
217
|
+
}];
|
|
218
|
+
};
|
|
219
|
+
SharedRPC::install(runtime, std::move(bgExecutor), "background");
|
|
220
|
+
[BTLogger info:@"SharedStore and SharedRPC installed in background runtime"];
|
|
221
|
+
invokeOptionalGlobalFunction(runtime, "__setupBackgroundRPCHandler");
|
|
201
222
|
}];
|
|
202
223
|
}
|
|
203
224
|
|
|
@@ -214,67 +235,6 @@ static std::string safeGetStringProperty(jsi::Runtime &rt, const jsi::Object &ob
|
|
|
214
235
|
return [super getTurboModule:name jsInvoker:jsInvoker];
|
|
215
236
|
}
|
|
216
237
|
|
|
217
|
-
- (jsi::Function)createPostMessageFunction:(jsi::Runtime &)runtime
|
|
218
|
-
{
|
|
219
|
-
return jsi::Function::createFromHostFunction(
|
|
220
|
-
runtime,
|
|
221
|
-
jsi::PropNameID::forAscii(runtime, "postMessage"),
|
|
222
|
-
2, // Updated to accept up to 2 arguments
|
|
223
|
-
[=](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *args, size_t count) {
|
|
224
|
-
// Validate runtime before any JSI operations
|
|
225
|
-
try {
|
|
226
|
-
rt.global(); // Test if runtime is accessible
|
|
227
|
-
} catch (...) {
|
|
228
|
-
return jsi::Value::undefined();
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
if (count < 1 || count > 2) {
|
|
232
|
-
throw jsi::JSError(rt, "Expected 1 or 2 arguments: postMessage(message, targetOrigin?)");
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
const jsi::Value &messageArg = args[0];
|
|
236
|
-
if (!messageArg.isString()) {
|
|
237
|
-
throw jsi::JSError(rt, "Expected an string as the first argument");
|
|
238
|
-
}
|
|
239
|
-
// jsi::Object jsonObject = rt.global().getPropertyAsObject(rt, "JSON");
|
|
240
|
-
// jsi::Function jsonStringify = jsonObject.getPropertyAsFunction(rt, "stringify");
|
|
241
|
-
// jsi::Value jsonResult = jsonStringify.call(rt, messageArg);
|
|
242
|
-
std::string messageJson = messageArg.getString(rt).utf8(rt);
|
|
243
|
-
NSString *messageNS = [NSString stringWithUTF8String:messageJson.c_str()];
|
|
244
|
-
dispatch_async(dispatch_get_main_queue(), ^{
|
|
245
|
-
if (self.onMessageCallback) {
|
|
246
|
-
self.onMessageCallback(messageNS);
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
return jsi::Value::undefined();
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
- (jsi::Function)createSetOnMessageFunction:(jsi::Runtime &)runtime
|
|
254
|
-
{
|
|
255
|
-
return jsi::Function::createFromHostFunction(
|
|
256
|
-
runtime,
|
|
257
|
-
jsi::PropNameID::forAscii(runtime, "setOnMessage"),
|
|
258
|
-
1,
|
|
259
|
-
[=](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *args, size_t count) {
|
|
260
|
-
if (count != 1) {
|
|
261
|
-
throw jsi::JSError(rt, "Expected exactly one argument");
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
const jsi::Value &arg = args[0];
|
|
265
|
-
if (!arg.isObject() || !arg.asObject(rt).isFunction(rt)) {
|
|
266
|
-
throw jsi::JSError(rt, "Expected a function as the first argument");
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
jsi::Function fn = arg.asObject(rt).asFunction(rt);
|
|
270
|
-
|
|
271
|
-
_onMessageSandbox.reset();
|
|
272
|
-
_onMessageSandbox = std::make_shared<jsi::Function>(std::move(fn));
|
|
273
|
-
|
|
274
|
-
return jsi::Value::undefined();
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
|
|
278
238
|
- (void)setupErrorHandler:(jsi::Runtime &)runtime
|
|
279
239
|
{
|
|
280
240
|
// Get ErrorUtils
|
package/ios/BackgroundThread.h
CHANGED
package/ios/BackgroundThread.mm
CHANGED
|
@@ -18,31 +18,15 @@
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
- (void)startBackgroundRunnerWithEntryURL:(NSString *)entryURL {
|
|
21
|
-
BackgroundThreadManager *manager = [BackgroundThreadManager sharedInstance];
|
|
22
|
-
[manager startBackgroundRunnerWithEntryURL:entryURL];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Force register event callback during initialization
|
|
26
|
-
// This is mainly to handle the scenario of restarting in development environment
|
|
27
|
-
- (void)initBackgroundThread {
|
|
28
|
-
[self bindMessageCallback];
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
- (void)bindMessageCallback {
|
|
32
21
|
BackgroundThreadManager *manager = [BackgroundThreadManager sharedInstance];
|
|
33
|
-
|
|
34
|
-
[manager setOnMessageCallback:^(NSString *message) {
|
|
35
|
-
[weakSelf emitOnBackgroundMessage:message];
|
|
36
|
-
}];
|
|
22
|
+
[manager startBackgroundRunnerWithEntryURL:entryURL];
|
|
37
23
|
}
|
|
38
24
|
|
|
39
|
-
- (void)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
[[BackgroundThreadManager sharedInstance] postBackgroundMessage:message];
|
|
25
|
+
- (void)installSharedBridge {
|
|
26
|
+
// On iOS, SharedBridge is installed from AppDelegate's hostDidStart: callback
|
|
27
|
+
// via +[BackgroundThreadManager installSharedBridgeInMainRuntime:].
|
|
28
|
+
// This is a no-op here — kept for API parity with Android.
|
|
29
|
+
[BTLogger info:@"installSharedBridge called (no-op on iOS, installed from AppDelegate)"];
|
|
46
30
|
}
|
|
47
31
|
|
|
48
32
|
+ (NSString *)moduleName
|
|
@@ -4,12 +4,18 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
4
4
|
|
|
5
5
|
@class BackgroundReactNativeDelegate;
|
|
6
6
|
@class RCTReactNativeFactory;
|
|
7
|
+
@class RCTHost;
|
|
7
8
|
|
|
8
9
|
@interface BackgroundThreadManager : NSObject
|
|
9
10
|
|
|
10
11
|
/// Shared instance for singleton pattern
|
|
11
12
|
+ (instancetype)sharedInstance;
|
|
12
13
|
|
|
14
|
+
/// Install SharedBridge HostObject into the main (UI) runtime.
|
|
15
|
+
/// Call this from your AppDelegate's ReactNativeDelegate hostDidStart: callback.
|
|
16
|
+
/// @param host The RCTHost for the main runtime
|
|
17
|
+
+ (void)installSharedBridgeInMainRuntime:(RCTHost *)host;
|
|
18
|
+
|
|
13
19
|
/// Start background runner with default entry URL
|
|
14
20
|
- (void)startBackgroundRunner;
|
|
15
21
|
|
|
@@ -17,18 +23,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
17
23
|
/// @param entryURL The custom entry URL for the background runner
|
|
18
24
|
- (void)startBackgroundRunnerWithEntryURL:(NSString *)entryURL;
|
|
19
25
|
|
|
20
|
-
/// Post message to background runner
|
|
21
|
-
/// @param message The message to post
|
|
22
|
-
- (void)postBackgroundMessage:(NSString *)message;
|
|
23
|
-
|
|
24
|
-
/// Set callback for handling background messages
|
|
25
|
-
/// @param callback The callback block to handle messages
|
|
26
|
-
- (void)setOnMessageCallback:(void (^)(NSString *message))callback;
|
|
27
|
-
|
|
28
|
-
/// Check if message callback is set
|
|
29
|
-
/// @return YES if message callback is set, NO otherwise
|
|
30
|
-
- (BOOL)checkMessageCallback;
|
|
31
|
-
|
|
32
26
|
/// Check if background runner is started
|
|
33
27
|
@property (nonatomic, readonly) BOOL isStarted;
|
|
34
28
|
|
|
@@ -15,12 +15,16 @@
|
|
|
15
15
|
#import "BackgroundRunnerReactNativeDelegate.h"
|
|
16
16
|
#import "BTLogger.h"
|
|
17
17
|
|
|
18
|
+
#include "SharedStore.h"
|
|
19
|
+
#include "SharedRPC.h"
|
|
20
|
+
#import <ReactCommon/RCTHost.h>
|
|
21
|
+
#import <objc/runtime.h>
|
|
22
|
+
|
|
18
23
|
@interface BackgroundThreadManager ()
|
|
19
24
|
@property (nonatomic, strong) BackgroundReactNativeDelegate *reactNativeFactoryDelegate;
|
|
20
25
|
@property (nonatomic, strong) RCTReactNativeFactory *reactNativeFactory;
|
|
21
26
|
@property (nonatomic, assign) BOOL hasListeners;
|
|
22
27
|
@property (nonatomic, assign, readwrite) BOOL isStarted;
|
|
23
|
-
@property (nonatomic, copy) void (^onMessageCallback)(NSString *message);
|
|
24
28
|
@end
|
|
25
29
|
|
|
26
30
|
@implementation BackgroundThreadManager
|
|
@@ -48,6 +52,37 @@ static NSString *const MODULE_DEBUG_URL = @"http://localhost:8082/apps/mobile/ba
|
|
|
48
52
|
return self;
|
|
49
53
|
}
|
|
50
54
|
|
|
55
|
+
#pragma mark - SharedBridge
|
|
56
|
+
|
|
57
|
+
+ (void)installSharedBridgeInMainRuntime:(RCTHost *)host {
|
|
58
|
+
if (!host) {
|
|
59
|
+
[BTLogger error:@"Cannot install SharedBridge: RCTHost is nil"];
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
Ivar ivar = class_getInstanceVariable([host class], "_instance");
|
|
64
|
+
id instance = object_getIvar(host, ivar);
|
|
65
|
+
|
|
66
|
+
if (!instance) {
|
|
67
|
+
[BTLogger error:@"Cannot install SharedBridge: RCTInstance is nil"];
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
[instance callFunctionOnBufferedRuntimeExecutor:^(facebook::jsi::Runtime &runtime) {
|
|
72
|
+
SharedStore::install(runtime);
|
|
73
|
+
|
|
74
|
+
// Install SharedRPC with executor for cross-runtime notifications
|
|
75
|
+
id capturedInstance = instance;
|
|
76
|
+
RPCRuntimeExecutor mainExecutor = [capturedInstance](std::function<void(jsi::Runtime &)> work) {
|
|
77
|
+
[capturedInstance callFunctionOnBufferedRuntimeExecutor:[work](jsi::Runtime &rt) {
|
|
78
|
+
work(rt);
|
|
79
|
+
}];
|
|
80
|
+
};
|
|
81
|
+
SharedRPC::install(runtime, std::move(mainExecutor), "main");
|
|
82
|
+
[BTLogger info:@"SharedStore and SharedRPC installed in main runtime"];
|
|
83
|
+
}];
|
|
84
|
+
}
|
|
85
|
+
|
|
51
86
|
#pragma mark - Public Methods
|
|
52
87
|
|
|
53
88
|
- (void)startBackgroundRunner {
|
|
@@ -71,39 +106,13 @@ static NSString *const MODULE_DEBUG_URL = @"http://localhost:8082/apps/mobile/ba
|
|
|
71
106
|
NSDictionary *launchOptions = @{};
|
|
72
107
|
self.reactNativeFactoryDelegate = [[BackgroundReactNativeDelegate alloc] init];
|
|
73
108
|
self.reactNativeFactory = [[RCTReactNativeFactory alloc] initWithDelegate:self.reactNativeFactoryDelegate];
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
#endif
|
|
78
|
-
|
|
109
|
+
|
|
110
|
+
[self.reactNativeFactoryDelegate setJsBundleSource:std::string([entryURL UTF8String])];
|
|
111
|
+
|
|
79
112
|
[self.reactNativeFactory.rootViewFactory viewWithModuleName:MODULE_NAME
|
|
80
113
|
initialProperties:initialProperties
|
|
81
114
|
launchOptions:launchOptions];
|
|
82
|
-
|
|
83
|
-
__weak __typeof__(self) weakSelf = self;
|
|
84
|
-
[self.reactNativeFactoryDelegate setOnMessageCallback:^(NSString *message) {
|
|
85
|
-
if (weakSelf.onMessageCallback) {
|
|
86
|
-
weakSelf.onMessageCallback(message);
|
|
87
|
-
}
|
|
88
|
-
}];
|
|
89
115
|
});
|
|
90
116
|
}
|
|
91
117
|
|
|
92
|
-
- (void)postBackgroundMessage:(NSString *)message {
|
|
93
|
-
if (self.reactNativeFactoryDelegate) {
|
|
94
|
-
[self.reactNativeFactoryDelegate postMessage:std::string([message UTF8String])];
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
- (void)setOnMessageCallback:(void (^)(NSString *message))callback {
|
|
99
|
-
_onMessageCallback = callback;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
- (BOOL)checkMessageCallback {
|
|
103
|
-
if (self.onMessageCallback) {
|
|
104
|
-
return YES;
|
|
105
|
-
}
|
|
106
|
-
return NO;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
118
|
@end
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeBackgroundThread.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAAQ,cAAc;
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeBackgroundThread.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAAQ,cAAc;AAQlD,eAAeA,mBAAmB,CAACC,YAAY,CAAO,kBAAkB,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["getSharedRPC","globalThis","sharedRPC"],"sourceRoot":"../../src","sources":["SharedRPC.ts"],"mappings":";;AAaA,OAAO,SAASA,YAAYA,CAAA,EAA2B;EACrD,OAAOC,UAAU,CAACC,SAAS;AAC7B","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["getSharedStore","globalThis","sharedStore"],"sourceRoot":"../../src","sources":["SharedStore.ts"],"mappings":";;AAeA,OAAO,SAASA,cAAcA,CAAA,EAA6B;EACzD,OAAOC,UAAU,CAACC,WAAW;AAC/B","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeBackgroundThread","BackgroundThread"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,sBAAsB,MAAM,6BAA0B;AAE7D,OAAO,MAAMC,gBAAgB,GAAGD,sBAAsB","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["NativeBackgroundThread","BackgroundThread","getSharedStore","getSharedRPC"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,sBAAsB,MAAM,6BAA0B;AAE7D,OAAO,MAAMC,gBAAgB,GAAGD,sBAAsB;AACtD,SAASE,cAAc,QAAQ,kBAAe;AAE9C,SAASC,YAAY,QAAQ,gBAAa","ignoreList":[]}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { TurboModule } from 'react-native';
|
|
2
2
|
export interface Spec extends TurboModule {
|
|
3
|
-
readonly onBackgroundMessage: CodegenTypes.EventEmitter<string>;
|
|
4
|
-
postBackgroundMessage(message: string): void;
|
|
5
3
|
startBackgroundRunnerWithEntryURL(entryURL: string): void;
|
|
6
|
-
|
|
4
|
+
installSharedBridge(): void;
|
|
7
5
|
}
|
|
8
6
|
declare const _default: Spec;
|
|
9
7
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeBackgroundThread.d.ts","sourceRoot":"","sources":["../../../src/NativeBackgroundThread.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"NativeBackgroundThread.d.ts","sourceRoot":"","sources":["../../../src/NativeBackgroundThread.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,iCAAiC,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1D,mBAAmB,IAAI,IAAI,CAAC;CAC7B;;AAED,wBAA0E"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface ISharedRPC {
|
|
2
|
+
write(callId: string, value: string | number | boolean): void;
|
|
3
|
+
read(callId: string): string | number | boolean | undefined;
|
|
4
|
+
has(callId: string): boolean;
|
|
5
|
+
readonly pendingCount: number;
|
|
6
|
+
onWrite(callback: (callId: string) => void): void;
|
|
7
|
+
}
|
|
8
|
+
declare global {
|
|
9
|
+
var sharedRPC: ISharedRPC | undefined;
|
|
10
|
+
}
|
|
11
|
+
export declare function getSharedRPC(): ISharedRPC | undefined;
|
|
12
|
+
//# sourceMappingURL=SharedRPC.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SharedRPC.d.ts","sourceRoot":"","sources":["../../../src/SharedRPC.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IAC9D,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IAC5D,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,OAAO,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;CACnD;AAED,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,SAAS,EAAE,UAAU,GAAG,SAAS,CAAC;CACvC;AAED,wBAAgB,YAAY,IAAI,UAAU,GAAG,SAAS,CAErD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface ISharedStore {
|
|
2
|
+
set(key: string, value: string | number | boolean): void;
|
|
3
|
+
get(key: string): string | number | boolean | undefined;
|
|
4
|
+
has(key: string): boolean;
|
|
5
|
+
delete(key: string): boolean;
|
|
6
|
+
keys(): string[];
|
|
7
|
+
clear(): void;
|
|
8
|
+
readonly size: number;
|
|
9
|
+
}
|
|
10
|
+
declare global {
|
|
11
|
+
var sharedStore: ISharedStore | undefined;
|
|
12
|
+
}
|
|
13
|
+
export declare function getSharedStore(): ISharedStore | undefined;
|
|
14
|
+
//# sourceMappingURL=SharedStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SharedStore.d.ts","sourceRoot":"","sources":["../../../src/SharedStore.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IACzD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IACxD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7B,IAAI,IAAI,MAAM,EAAE,CAAC;IACjB,KAAK,IAAI,IAAI,CAAC;IACd,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,WAAW,EAAE,YAAY,GAAG,SAAS,CAAC;CAC3C;AAED,wBAAgB,cAAc,IAAI,YAAY,GAAG,SAAS,CAEzD"}
|
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
export declare const BackgroundThread: import("./NativeBackgroundThread").Spec;
|
|
2
|
+
export { getSharedStore } from './SharedStore';
|
|
3
|
+
export type { ISharedStore } from './SharedStore';
|
|
4
|
+
export { getSharedRPC } from './SharedRPC';
|
|
5
|
+
export type { ISharedRPC } from './SharedRPC';
|
|
2
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAEA,eAAO,MAAM,gBAAgB,yCAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAEA,eAAO,MAAM,gBAAgB,yCAAyB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/react-native-background-thread",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.48",
|
|
4
4
|
"description": "react-native-background-thread",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"lefthook": "^2.0.3",
|
|
77
77
|
"prettier": "^2.8.8",
|
|
78
78
|
"react": "19.2.0",
|
|
79
|
-
"react-native": "0.83.0",
|
|
79
|
+
"react-native": "patch:react-native@npm%3A0.83.0#~/.yarn/patches/react-native-npm-0.83.0-577d0f2d83.patch",
|
|
80
80
|
"react-native-builder-bob": "^0.40.17",
|
|
81
81
|
"release-it": "^19.0.4",
|
|
82
82
|
"turbo": "^2.5.6",
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { TurboModuleRegistry } from 'react-native';
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { TurboModule } from 'react-native';
|
|
4
4
|
export interface Spec extends TurboModule {
|
|
5
|
-
readonly onBackgroundMessage: CodegenTypes.EventEmitter<string>;
|
|
6
|
-
postBackgroundMessage(message: string): void;
|
|
7
5
|
startBackgroundRunnerWithEntryURL(entryURL: string): void;
|
|
8
|
-
|
|
6
|
+
installSharedBridge(): void;
|
|
9
7
|
}
|
|
10
8
|
|
|
11
9
|
export default TurboModuleRegistry.getEnforcing<Spec>('BackgroundThread');
|
package/src/SharedRPC.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface ISharedRPC {
|
|
2
|
+
write(callId: string, value: string | number | boolean): void;
|
|
3
|
+
read(callId: string): string | number | boolean | undefined;
|
|
4
|
+
has(callId: string): boolean;
|
|
5
|
+
readonly pendingCount: number;
|
|
6
|
+
onWrite(callback: (callId: string) => void): void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
declare global {
|
|
10
|
+
// eslint-disable-next-line no-var
|
|
11
|
+
var sharedRPC: ISharedRPC | undefined;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function getSharedRPC(): ISharedRPC | undefined {
|
|
15
|
+
return globalThis.sharedRPC;
|
|
16
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ISharedStore {
|
|
2
|
+
set(key: string, value: string | number | boolean): void;
|
|
3
|
+
get(key: string): string | number | boolean | undefined;
|
|
4
|
+
has(key: string): boolean;
|
|
5
|
+
delete(key: string): boolean;
|
|
6
|
+
keys(): string[];
|
|
7
|
+
clear(): void;
|
|
8
|
+
readonly size: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
declare global {
|
|
12
|
+
// eslint-disable-next-line no-var
|
|
13
|
+
var sharedStore: ISharedStore | undefined;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function getSharedStore(): ISharedStore | undefined {
|
|
17
|
+
return globalThis.sharedStore;
|
|
18
|
+
}
|
package/src/index.tsx
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import NativeBackgroundThread from './NativeBackgroundThread';
|
|
2
2
|
|
|
3
3
|
export const BackgroundThread = NativeBackgroundThread;
|
|
4
|
+
export { getSharedStore } from './SharedStore';
|
|
5
|
+
export type { ISharedStore } from './SharedStore';
|
|
6
|
+
export { getSharedRPC } from './SharedRPC';
|
|
7
|
+
export type { ISharedRPC } from './SharedRPC';
|