@exodus/react-native-webview 13.16.0-exodus.6 → 13.16.0-exodus.7
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.
|
@@ -3,11 +3,15 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* Exodus: Thread-safe singleton that manages navigation decision handlers.
|
|
5
5
|
*
|
|
6
|
+
* All public methods use @synchronized for thread safety, and decision
|
|
7
|
+
* handlers are invoked outside the lock to avoid deadlocks
|
|
8
|
+
* (upstream react-native-webview#3916).
|
|
9
|
+
*
|
|
6
10
|
* Security improvements over upstream:
|
|
7
11
|
* - Uses NSInteger (64-bit) instead of int to prevent overflow
|
|
8
12
|
* - Adds collision checking to skip identifiers still in use
|
|
9
|
-
* - All public methods use @synchronized for thread safety
|
|
10
13
|
* - Explicitly copies blocks to heap to prevent use-after-free
|
|
14
|
+
* - Denies navigation by default if JS does not respond within 500ms
|
|
11
15
|
* - Provides cancelDecisionForLockIdentifier: for cleanup on WebView dealloc
|
|
12
16
|
*/
|
|
13
17
|
@implementation RNCWebViewDecisionManager
|
|
@@ -40,14 +44,17 @@
|
|
|
40
44
|
// if JS responded in time.
|
|
41
45
|
NSInteger capturedIdentifier = lockIdentifier;
|
|
42
46
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(500 * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
|
|
47
|
+
DecisionBlock pendingHandler;
|
|
43
48
|
@synchronized (self) {
|
|
44
|
-
|
|
45
|
-
if (pendingHandler
|
|
46
|
-
|
|
47
|
-
pendingHandler(NO);
|
|
48
|
-
[self.decisionHandlers removeObjectForKey:@(capturedIdentifier)];
|
|
49
|
+
pendingHandler = [self.decisionHandlers objectForKey:@(capturedIdentifier)];
|
|
50
|
+
if (pendingHandler == nil) {
|
|
51
|
+
return;
|
|
49
52
|
}
|
|
53
|
+
[self.decisionHandlers removeObjectForKey:@(capturedIdentifier)];
|
|
50
54
|
}
|
|
55
|
+
// Invoke outside the lock, as in setResult:forLockIdentifier:.
|
|
56
|
+
RCTLogWarn(@"Navigation decision timeout for lock %ld, denying by default", (long)capturedIdentifier);
|
|
57
|
+
pendingHandler(NO);
|
|
51
58
|
});
|
|
52
59
|
|
|
53
60
|
return lockIdentifier;
|
|
@@ -55,15 +62,20 @@
|
|
|
55
62
|
}
|
|
56
63
|
|
|
57
64
|
- (void)setResult:(BOOL)shouldStart forLockIdentifier:(NSInteger)lockIdentifier {
|
|
65
|
+
// The handler is captured and removed under the lock, then invoked OUTSIDE
|
|
66
|
+
// it (upstream react-native-webview#3916). The handler hops to the main
|
|
67
|
+
// queue and can trigger another navigation that re-enters this class, so
|
|
68
|
+
// holding the lock across its invocation risks deadlock.
|
|
69
|
+
DecisionBlock handler;
|
|
58
70
|
@synchronized (self) {
|
|
59
|
-
|
|
71
|
+
handler = [self.decisionHandlers objectForKey:@(lockIdentifier)];
|
|
60
72
|
if (handler == nil) {
|
|
61
73
|
RCTLogWarn(@"Lock not found for identifier: %ld", (long)lockIdentifier);
|
|
62
74
|
return;
|
|
63
75
|
}
|
|
64
|
-
handler(shouldStart);
|
|
65
76
|
[self.decisionHandlers removeObjectForKey:@(lockIdentifier)];
|
|
66
77
|
}
|
|
78
|
+
handler(shouldStart);
|
|
67
79
|
}
|
|
68
80
|
|
|
69
81
|
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"Thibault Malbranche <malbranche.thibault@gmail.com>"
|
|
11
11
|
],
|
|
12
12
|
"license": "MIT",
|
|
13
|
-
"version": "13.16.0-exodus.
|
|
13
|
+
"version": "13.16.0-exodus.7",
|
|
14
14
|
"homepage": "https://github.com/ExodusMovement/react-native-webview#readme",
|
|
15
15
|
"scripts": {
|
|
16
16
|
"android": "react-native run-android",
|