diff --git a/Libraries/Components/WebView/WebView.ios.js b/Libraries/Components/WebView/WebView.ios.js index 018f913d1c4..109035aec5b 100644 --- a/Libraries/Components/WebView/WebView.ios.js +++ b/Libraries/Components/WebView/WebView.ios.js @@ -461,6 +461,16 @@ var WebView = React.createClass({ ); }, + /** + * Evaluate JavaScript on the current page. + */ + evaluateJavaScript: async function(script: string): Promise { + var escaped = JSON.stringify(script).replace(/\u2028/g, '\\u2028').replace(/\u2029/g, '\\u2029'); + var wrapped = 'JSON.stringify(eval(' + escaped + '))'; + var resultString = await RCTWebViewManager.evaluateJavaScript(this.getWebViewHandle(), wrapped); + return JSON.parse(resultString); + }, + /** * We return an event with a bunch of fields including: * url, title, loading, canGoBack, canGoForward diff --git a/React/Views/RCTWebView.h b/React/Views/RCTWebView.h index f8bd2608cc0..0b3bbb71ccb 100644 --- a/React/Views/RCTWebView.h +++ b/React/Views/RCTWebView.h @@ -41,5 +41,6 @@ shouldStartLoadForRequest:(NSMutableDictionary *)request - (void)goBack; - (void)reload; - (void)stopLoading; +- (NSString *)evaluateJavaScript:(NSString *)script; @end diff --git a/React/Views/RCTWebView.m b/React/Views/RCTWebView.m index 76c3f096003..e103417ca1e 100644 --- a/React/Views/RCTWebView.m +++ b/React/Views/RCTWebView.m @@ -82,6 +82,11 @@ - (void)stopLoading [_webView stopLoading]; } +- (NSString *)evaluateJavaScript:(NSString*)script +{ + return [_webView stringByEvaluatingJavaScriptFromString: script]; +} + - (void)setSource:(NSDictionary *)source { if (![_source isEqualToDictionary:source]) { diff --git a/React/Views/RCTWebViewManager.m b/React/Views/RCTWebViewManager.m index af5f5b03b8a..ef4cf9a7bc4 100644 --- a/React/Views/RCTWebViewManager.m +++ b/React/Views/RCTWebViewManager.m @@ -13,6 +13,7 @@ #import "RCTUIManager.h" #import "RCTWebView.h" #import "UIView+React.h" +#import "RCTUtils.h" @interface RCTWebViewManager () @@ -97,6 +98,24 @@ - (UIView *)view }]; } +RCT_REMAP_METHOD(evaluateJavaScript, evaluateJavaScript:(nonnull NSNumber *)reactTag script:(nonnull NSString *)script resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + RCTWebView *view = viewRegistry[reactTag]; + if (![view isKindOfClass:[RCTWebView class]]) { + RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); + return; + } + + NSString *result = [view evaluateJavaScript: script]; + if (result && [result length] > 0) { + resolve(result); + } else { + reject(RCTErrorUnspecified, @"Error evaluating script.", nil); + } + }]; +} + #pragma mark - Exported synchronous methods - (BOOL)webView:(__unused RCTWebView *)webView