From 7a1f974c8019b1840d196546345d06a03ff83d06 Mon Sep 17 00:00:00 2001 From: Kirill Bulgakov Date: Wed, 14 Jan 2026 00:46:51 +0300 Subject: [PATCH 1/2] feat: respect `shouldStartLoadTimeout` parameter --- apple/RNCWebView.h | 1 + apple/RNCWebViewManager.m | 8 ++++++-- src/WebView.ios.tsx | 4 +++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/apple/RNCWebView.h b/apple/RNCWebView.h index 0ce544db3a..98c868ebd1 100644 --- a/apple/RNCWebView.h +++ b/apple/RNCWebView.h @@ -71,6 +71,7 @@ shouldStartLoadForRequest:(NSMutableDictionary *_Nonnull)request @property (nonatomic, copy) NSDictionary * _Nullable basicAuthCredential; @property (nonatomic, assign) BOOL pullToRefreshEnabled; @property (nonatomic, assign) BOOL enableApplePay; +@property (nonatomic, assign) NSInteger shouldStartLoadTimeout; @property (nonatomic, copy) NSArray * _Nullable menuItems; @property (nonatomic, copy) RCTDirectEventBlock onCustomMenuSelection; #if !TARGET_OS_OSX diff --git a/apple/RNCWebViewManager.m b/apple/RNCWebViewManager.m index b5b76cbd3e..54e2035f7f 100644 --- a/apple/RNCWebViewManager.m +++ b/apple/RNCWebViewManager.m @@ -113,6 +113,8 @@ - (RCTUIView *)view RCT_EXPORT_VIEW_PROPERTY(menuItems, NSArray); RCT_EXPORT_VIEW_PROPERTY(onCustomMenuSelection, RCTDirectEventBlock) +RCT_EXPORT_VIEW_PROPERTY(shouldStartLoadTimeout, NSInteger) + RCT_EXPORT_METHOD(postMessage:(nonnull NSNumber *)reactTag message:(NSString *)message) { [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { @@ -254,8 +256,10 @@ - (BOOL) webView:(RNCWebView *)webView request[@"lockIdentifier"] = @(_shouldStartLoadLock.condition); callback(request); - // Block the main thread for a maximum of 500ms until the JS thread returns - if ([_shouldStartLoadLock lockWhenCondition:0 beforeDate:[NSDate dateWithTimeIntervalSinceNow:.50]]) { + NSInteger timeoutMs = webView.shouldStartLoadTimeout; + NSTimeInterval timeoutSeconds = timeoutMs / 1000.0; + + if ([_shouldStartLoadLock lockWhenCondition:0 beforeDate:[NSDate dateWithTimeIntervalSinceNow:timeoutSeconds]]) { BOOL returnValue = _shouldStartLoad; [_shouldStartLoadLock unlock]; _shouldStartLoadLock = nil; diff --git a/src/WebView.ios.tsx b/src/WebView.ios.tsx index 0189bdde24..e7d513ba11 100644 --- a/src/WebView.ios.tsx +++ b/src/WebView.ios.tsx @@ -74,7 +74,8 @@ const WebViewComponent = forwardRef<{}, IOSWebViewProps>((props, ref) => { cacheEnabled = true, originWhitelist = defaultOriginWhitelist, deeplinkWhitelist = defaultDeeplinkWhitelist, - textInteractionEnabled= true, + textInteractionEnabled = true, + shouldStartLoadTimeout = 500, injectedJavaScript, injectedJavaScriptBeforeContentLoaded, startInLoadingState, @@ -208,6 +209,7 @@ const WebViewComponent = forwardRef<{}, IOSWebViewProps>((props, ref) => { mediaPlaybackRequiresUserAction={mediaPlaybackRequiresUserAction} ref={webViewRef} sharedCookiesEnabled={sharedCookiesEnabled} + shouldStartLoadTimeout={shouldStartLoadTimeout} // TODO: find a better way to type this. source={source} style={webViewStyles} From 35206b06f3de6a58c6438912c3c3ae769ccbcdec Mon Sep 17 00:00:00 2001 From: Kirill Bulgakov Date: Wed, 14 Jan 2026 00:47:31 +0300 Subject: [PATCH 2/2] feat: update types --- src/WebViewTypes.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/WebViewTypes.ts b/src/WebViewTypes.ts index 0de7379d70..9bf26687cd 100644 --- a/src/WebViewTypes.ts +++ b/src/WebViewTypes.ts @@ -321,6 +321,7 @@ export interface IOSNativeWebViewProps extends CommonNativeWebViewProps { enableApplePay?: boolean; textInteractionEnabled?: boolean; mediaCapturePermissionGrantType?: MediaCapturePermissionGrantType; + shouldStartLoadTimeout?: number; } export interface IOSWebViewProps extends WebViewSharedProps { @@ -573,6 +574,15 @@ export interface IOSWebViewProps extends WebViewSharedProps { * @platform ios */ onCustomMenuSelection?: (event: WebViewEvent) => void; + + /** + * Timeout in milliseconds for the shouldStartLoad callback to respond. + * If the JS thread is busy and cannot respond within this time, navigation + * will be blocked. + * The default value is `500`. + * @platform ios + */ + shouldStartLoadTimeout?: number; } export interface AndroidWebViewProps extends WebViewSharedProps {