-
Notifications
You must be signed in to change notification settings - Fork 3
feat: support async onShouldStartLoad requests #49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Co-authored-by: Thibault Malbranche <malbranche.thibault@gmail.com>
| int lockIdentifier = [[RNCWebViewDecisionManager getInstance] setDecisionHandler:^(BOOL shouldStart) { | ||
| dispatch_async(dispatch_get_main_queue(), ^{ | ||
| if (!shouldStart) { | ||
| decisionHandler(WKNavigationActionPolicyCancel); | ||
| return; | ||
| } | ||
| allowNavigation(); | ||
| }); | ||
| }]; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The allowing code is moved into the allowNavigation helper to be reused below to keep the old fallback behavior
apple/RNCWebViewManager.m
Outdated
| RCTLogWarn(@"startLoadWithResult invoked with invalid lockIdentifier: " | ||
| "got %lld, expected %lld", (long long)lockIdentifier, (long long)_shouldStartLoadLock.condition); | ||
| } | ||
| [[RNCWebViewDecisionManager getInstance] setResult:result forLockIdentifier:(int)lockIdentifier]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kbulgakov-exo
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tACK
- WebView loads content normally when JS responds with
true - WebView rejects loading when JS responds with
false
guten-exodus
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK nice
|
@guten-exodus Could you check whether this also addresses the pain points you had in Pay? |
timlanahan
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ChALkeR please review
Tested, worked great! |
apple/RNCWebViewDecisionManager.m
Outdated
| } | ||
|
|
||
| - (int)setDecisionHandler:(DecisionBlock)decisionHandler { | ||
| int lockIdentifier = self.nextLockIdentifier++; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doesn't look very thread safe - not sure if it needs to be though
- the
++isn't an atomic add operation, so two threads calling it at the same time are essentially getting the same lock identifier. Since I believe this will only be called from the main thread, I think this is fine-ish (?)
But NSMutableArray isn't thread safe, so if multiple threads are adding & removing things at the same time then things may go wrong :|
setDecisionHandler is called from webView:decidePolicyForNavigationAction which runs on the main thread afaik and setResult is exported to React Native to be called from JS which is another thread? So there might be some rare race conditions here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested b6cad2e, all good. Thanks!
kewdex
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK
The existing approach with locking the main thread to make a synchronous call asking JS "can I proceed with this URL" isn't reliable. Even the recent timeout bump to 500ms #47 didn't help, we still experience the loading issues. Bumping the timeout even more (for example with #48) would inevitably lead to performance degradation because of the locked thread. We should come up with a more reliable solution
The bottleneck
I've put some logs to diagnose what exactly is the bottleneck. The JS callback works super fast, but the problem is that sometimes it seems to be called after Native already makes the decision after the 500ms default timeout:
The solution
Let's mirror the async architecture of the
onShouldStartLoadcalls from https://github.com/react-native-webview/react-native-webview. We can easily backport most of the code.I recommend reviewing commit by commit
Notes:
WebViewDecisionManagerfrom upstream with minor formatting changesTesting
truefalse