[iOS] `injectedJavaScriptObject` updates are not applied to an existing WKWebView (frozen at creation-time value)
Bug description:
On iOS, changing the injectedJavaScriptObject prop after the WebView has mounted has no effect on the live WKWebView. The value returned by window.ReactNativeWebView.injectedObjectJson() is frozen at whatever it was when the WebView was first created. Any subsequent full page load in the same WebView re-runs the original injected object, not the updated one.
To Reproduce:
- Render a WebView whose
injectedJavaScriptObjectcontains a value (e.g.{ value: "A" }) - Update
injectedJavaScriptObjectto{ value: "B" }and trigger a full page load in the same WebView by changing the URL (or using.reload()) - Inside the page at document start, read
JSON.parse(window.ReactNativeWebView.injectedObjectJson()). It's still{ value: "A" }
Expected behavior:
After a reload/URL change the value reflects the latest injectedJavaScriptObject prop.
postMessage / injectedJavaScript cannot reliably help here: the web content reads injectedObjectJson() at document start, before the JS message listener exists, so the value must be correct in the registered WKUserScript at that moment.
In apple/RNCWebViewImpl.m, the setter setInjectedJavaScriptObject rebuilds the WKUserScript (self.injectedObjectJsonScript) with the new value but it never calls resetupScripts while all other setter, e.g. setEnableApplePay:, do:
- (void)setInjectedJavaScriptObject:(NSString *)source
{
_injectedJavaScriptObject = source;
self.injectedObjectJsonScript = [
[WKUserScript alloc]
initWithSource: [
NSString
stringWithFormat:
@"window.%@ = window.%@ || {};"
"window.%@.injectedObjectJson = function () {"
" return `%@`;"
"};", MessageHandlerName, MessageHandlerName, MessageHandlerName, source
]
injectionTime:WKUserScriptInjectionTimeAtDocumentStart
/* TODO: For a separate (minor) PR: use logic like this (as react-native-wkwebview does) so that messaging can be used in all frames if desired.
* I am keeping it as YES for consistency with previous behaviour. */
// forMainFrameOnly:_messagingEnabledForMainFrameOnly
forMainFrameOnly:YES
];
// <---- no resetupScripts
}
- (void)setEnableApplePay:(BOOL)enableApplePay {
_enableApplePay = enableApplePay;
if(_webView != nil){
[self resetupScripts:_webView.configuration];
}
}Is there a reason for this?
Environment:
- OS: macOS
- OS version: 26.6.2
- react-native version: 0.86
- react-native-webview: 16.0.0 (also present in 13.16.1)
- Platform: iOS (WKWebView)
- The equivalent Android path works
Source: react-native-webview/react-native-webview