Files
react-native/Libraries/LinkingIOS/RCTLinkingManager.mm
T
Ramanpreet Nara 03bd7d799e Part 2: Update ObjC++ codegen classes to use ObjCTurboModule::InitParams
Summary:
## Summary
Please check out D21035209.

## Changes
- Codemod all ObjC NativeModule `getTurboModuleWithJsInvoker:nativeInvoker:perfLogger` methods to `getTurboModule:(const ObjCTurboModule::Args)`

## Script
```
var withSpaces = (...args) => args.join('\s*')

var regexString = withSpaces(
  '-',
  '\(',
  'std::shared_ptr',
  '<',
  '(?<turboModuleClass>(facebook::react::|react::|::|)TurboModule)',
  '>',
  '\)',
  'getTurboModuleWithJsInvoker',
  ':',
  '\(',
  'std::shared_ptr',
  '<',
  '(?<fbNamespace>(facebook::react::|react::|::|))CallInvoker',
  '>',
  '\)',
  '(?<jsInvokerInstance>[A-Za-z0-9]+)',
  'nativeInvoker',
  ':',
  '\(',
  'std::shared_ptr',
  '<',
  '(facebook::react::|react::|::|)CallInvoker',
  '>',
  '\)',
  '(?<nativeInvokerInstance>[A-Za-z0-9]+)',
  'perfLogger',
  ':',
  '\(',
  'id',
  '<',
  'RCTTurboModulePerformanceLogger',
  '>',
  '\)',
  '(?<perfLoggerInstance>[A-Za-z0-9]+)',
  '{',
  'return',
  'std::make_shared',
  '<',
  '(?<specName>(facebook::react::|react::|::|)Native[%A-Za-z0-9]+SpecJSI)',
  '>',
  '\(',
  'self',
  ',',
  '\k<jsInvokerInstance>',
  ',',
  '\k<nativeInvokerInstance>',
  ',',
  '\k<perfLoggerInstance>',
  '\)',
  ';',
  '}',
)

var replaceString = `- (std::shared_ptr<$<turboModuleClass>>) getTurboModule:(const $<fbNamespace>ObjCTurboModule::InitParams &)params
{
  return std::make_shared<$<specName>>(params);
}`

const exec = require('../lib/exec');
const abspath = require('../lib/abspath');
const relpath = require('../lib/relpath');
const readFile = (filename) => require('fs').readFileSync(filename, 'utf8');
const writeFile = (filename, content) => require('fs').writeFileSync(filename, content);

function main() {
  const tmFiles = exec('cd ~/fbsource && xbgs -n 10000 -l getTurboModuleWithJsInvoker:').split('\n').filter(Boolean);

  tmFiles
    .filter((filename) => !filename.includes('microsoft-fork-of-react-native'))
    .map(abspath)
    .forEach((filename) => {
      const source = readFile(filename);
      const newSource = source.replace(new RegExp(regexString, 'g'), replaceString);

      if (source == newSource) {
        console.log(relpath(filename));
      }

      writeFile(filename, newSource);
    });
}

if (!module.parent) {
  main();
}
```

## Re-generating diff
```
> hg revert -r .^ --all
> node index.js # run script
```

Changelog: [iOS][Changed] - Make all ObjC NativeModules create TurboModules using ObjCTurboModule::Args

Reviewed By: PeteTheHeat

Differential Revision: D21036265

fbshipit-source-id: 404bcc548d1775ef23d793527606d02fe384a0a2
2020-04-16 17:29:55 -07:00

199 lines
6.7 KiB
Plaintext

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/RCTLinkingManager.h>
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTBridge.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTUtils.h>
#import <React/RCTLog.h>
#import "RCTLinkingPlugins.h"
static NSString *const kOpenURLNotification = @"RCTOpenURLNotification";
static void postNotificationWithURL(NSURL *URL, id sender)
{
NSDictionary<NSString *, id> *payload = @{@"url": URL.absoluteString};
[[NSNotificationCenter defaultCenter] postNotificationName:kOpenURLNotification
object:sender
userInfo:payload];
}
@interface RCTLinkingManager() <NativeLinkingSpec>
@end
@implementation RCTLinkingManager
RCT_EXPORT_MODULE()
- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}
- (void)startObserving
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleOpenURLNotification:)
name:kOpenURLNotification
object:nil];
}
- (void)stopObserving
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (NSArray<NSString *> *)supportedEvents
{
return @[@"url"];
}
+ (BOOL)application:(UIApplication *)app
openURL:(NSURL *)URL
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
postNotificationWithURL(URL, self);
return YES;
}
// Corresponding api deprecated in iOS 9
+ (BOOL)application:(UIApplication *)application
openURL:(NSURL *)URL
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
{
postNotificationWithURL(URL, self);
return YES;
}
+ (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 12000) /* __IPHONE_12_0 */
(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> *_Nullable))restorationHandler {
#else
(nonnull void (^)(NSArray *_Nullable))restorationHandler {
#endif
if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
NSDictionary *payload = @{@"url": userActivity.webpageURL.absoluteString};
[[NSNotificationCenter defaultCenter] postNotificationName:kOpenURLNotification
object:self
userInfo:payload];
}
return YES;
}
- (void)handleOpenURLNotification:(NSNotification *)notification
{
[self sendEventWithName:@"url" body:notification.userInfo];
}
RCT_EXPORT_METHOD(openURL:(NSURL *)URL
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
{
[RCTSharedApplication() openURL:URL options:@{} completionHandler:^(BOOL success) {
if (success) {
resolve(@YES);
} else {
#if TARGET_OS_SIMULATOR
// Simulator-specific code
if([URL.absoluteString hasPrefix:@"tel:"]){
RCTLogWarn(@"Unable to open the Phone app in the simulator for telephone URLs. URL: %@", URL);
resolve(@NO);
} else {
reject(RCTErrorUnspecified, [NSString stringWithFormat:@"Unable to open URL: %@", URL], nil);
}
#else
// Device-specific code
reject(RCTErrorUnspecified, [NSString stringWithFormat:@"Unable to open URL: %@", URL], nil);
#endif
}
}];
}
RCT_EXPORT_METHOD(canOpenURL:(NSURL *)URL
resolve:(RCTPromiseResolveBlock)resolve
reject:(__unused RCTPromiseRejectBlock)reject)
{
if (RCTRunningInAppExtension()) {
// Technically Today widgets can open urls, but supporting that would require
// a reference to the NSExtensionContext
resolve(@NO);
return;
}
// This can be expensive, so we deliberately don't call on main thread
BOOL canOpen = [RCTSharedApplication() canOpenURL:URL];
NSString *scheme = [URL scheme];
if (canOpen) {
resolve(@YES);
} else if (![[scheme lowercaseString] hasPrefix:@"http"] && ![[scheme lowercaseString] hasPrefix:@"https"]) {
// On iOS 9 and above canOpenURL returns NO without a helpful error.
// Check if a custom scheme is being used, and if it exists in LSApplicationQueriesSchemes
NSArray *querySchemes = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"LSApplicationQueriesSchemes"];
if (querySchemes != nil && ([querySchemes containsObject:scheme] || [querySchemes containsObject:[scheme lowercaseString]])) {
resolve(@NO);
} else {
reject(RCTErrorUnspecified, [NSString stringWithFormat:@"Unable to open URL: %@. Add %@ to LSApplicationQueriesSchemes in your Info.plist.", URL, scheme], nil);
}
} else {
resolve(@NO);
}
}
RCT_EXPORT_METHOD(getInitialURL:(RCTPromiseResolveBlock)resolve
reject:(__unused RCTPromiseRejectBlock)reject)
{
NSURL *initialURL = nil;
if (self.bridge.launchOptions[UIApplicationLaunchOptionsURLKey]) {
initialURL = self.bridge.launchOptions[UIApplicationLaunchOptionsURLKey];
} else {
NSDictionary *userActivityDictionary =
self.bridge.launchOptions[UIApplicationLaunchOptionsUserActivityDictionaryKey];
if ([userActivityDictionary[UIApplicationLaunchOptionsUserActivityTypeKey] isEqual:NSUserActivityTypeBrowsingWeb]) {
initialURL = ((NSUserActivity *)userActivityDictionary[@"UIApplicationLaunchOptionsUserActivityKey"]).webpageURL;
}
}
resolve(RCTNullIfNil(initialURL.absoluteString));
}
RCT_EXPORT_METHOD(openSettings:(RCTPromiseResolveBlock)resolve
reject:(__unused RCTPromiseRejectBlock)reject)
{
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
[RCTSharedApplication() openURL:url options:@{} completionHandler:^(BOOL success) {
if (success) {
resolve(nil);
} else {
reject(RCTErrorUnspecified, @"Unable to open app settings", nil);
}
}];
}
RCT_EXPORT_METHOD(sendIntent:(NSString *)action
extras:(NSArray *_Nullable)extras
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
{
RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd));
}
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params
{
return std::make_shared<facebook::react::NativeLinkingSpecJSI>(params);
}
@end
Class RCTLinkingManagerCls(void) {
return RCTLinkingManager.class;
}