react-native-macos/React/CoreModules/RCTAlertManager.mm

205 строки
7.2 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 "RCTAlertManager.h"
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <RCTTypeSafety/RCTConvertHelpers.h>
#import <React/RCTAssert.h>
#import <React/RCTConvert.h>
#import <React/RCTLog.h>
#import <React/RCTUtils.h>
#import "CoreModulesPlugins.h"
iOS: Update RCTAlertManager to use new RCTAlertController (#29295) Summary: This should fix https://github.com/facebook/react-native/issues/29082 and https://github.com/facebook/react-native/issues/10471 Currently when an alert is being shown while a modal is being dismissed, it causes the alert not to show and In some cases it causes the UI to become unresponsive. I think this was caused by using RCTPresentedViewController to try and display the Alert the currently presented view. The View the Alert was going to be shown on is dismissed and the modal doesn't show. I implemented a new RCTAlertController to show the alert on top of the view, the modal being dismissed should now not interfere with the alert being shown. ## Changelog [iOS] [Fixed] - Fixed showing Alert while closing a Modal Pull Request resolved: https://github.com/facebook/react-native/pull/29295 Test Plan: To recreate the bug: 1. npx react-native init Test --version 0.63.0-rc.1 2. Paste the following code into App.js ```javascript /** * Sample React Native App * https://github.com/facebook/react-native * * format * flow strict-local */ import React from 'react'; import { SafeAreaView, StyleSheet, View, Text, StatusBar, Modal, Alert } from 'react-native'; const App: () => React$Node = () => { const [visible, setVisible] = React.useState(false) const onShowModal = () => { setVisible(true) } onCloseBroken = () => { setVisible(false) Alert.alert('Alert', 'Alert won\'t show') } onCloseWorking = () => { setVisible(false) setTimeout(() => Alert.alert('Alert', 'Works fine'), 10) } return ( <> <StatusBar barStyle="dark-content" /> <SafeAreaView style={styles.container}> <Text onPress={onShowModal}>Show modal</Text> </SafeAreaView> <Modal animationType="fade" visible={visible} onRequestClose={onCloseWorking} > <View style={styles.container}> <Text onPress={onCloseBroken}>Close modal immediately</Text> <Text onPress={onCloseWorking}>Close modal with delay</Text> </View> </Modal> </> ) } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'space-around', }, }) export default App ``` 3. cd Test && npx react-native run-ios 4. Show the modal and click the `Close modal immediately` button The first button doesn't show the alert, the second does because it gets rendered after the modal view is dismissed. After this commit, the alert always shows on top of every view properly. You can test by pointing the react native package to my branch by modifying the package json file like this ``` "react-native": "https://github.com/devon94/react-native.git#fix-ios-modal" ``` I was unable to reproduce the case where it causes the UI to be responsive in the test app but was able to reproduce it in our react native app at work. I can provide a video later if needed but the code is too complex to simplify into a test case. Reviewed By: sammy-SC Differential Revision: D22783371 Pulled By: PeteTheHeat fbshipit-source-id: 3e359645c610074ea855ee5686c59bdb9d6b696b
2020-08-07 02:18:31 +03:00
#import "RCTAlertController.h"
@implementation RCTConvert (UIAlertViewStyle)
RCT_ENUM_CONVERTER(
RCTAlertViewStyle,
(@{
@"default" : @(RCTAlertViewStyleDefault),
@"secure-text" : @(RCTAlertViewStyleSecureTextInput),
@"plain-text" : @(RCTAlertViewStylePlainTextInput),
@"login-password" : @(RCTAlertViewStyleLoginAndPasswordInput),
}),
RCTAlertViewStyleDefault,
integerValue)
@end
@interface RCTAlertManager () <NativeAlertManagerSpec>
@end
@implementation RCTAlertManager {
NSHashTable *_alertControllers;
}
RCT_EXPORT_MODULE()
- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}
- (void)invalidate
{
for (UIAlertController *alertController in _alertControllers) {
[alertController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
}
/**
* @param {NSDictionary} args Dictionary of the form
*
* @{
* @"message": @"<Alert message>",
* @"buttons": @[
* @{@"<key1>": @"<title1>"},
* @{@"<key2>": @"<title2>"},
* ],
* @"cancelButtonKey": @"<key2>",
* }
* The key from the `buttons` dictionary is passed back in the callback on click.
* Buttons are displayed in the order they are specified.
*/
RCT_EXPORT_METHOD(alertWithArgs : (JS::NativeAlertManager::Args &)args callback : (RCTResponseSenderBlock)callback)
{
NSString *title = [RCTConvert NSString:args.title()];
NSString *message = [RCTConvert NSString:args.message()];
RCTAlertViewStyle type = [RCTConvert RCTAlertViewStyle:args.type()];
NSArray<NSDictionary *> *buttons =
[RCTConvert NSDictionaryArray:RCTConvertOptionalVecToArray(args.buttons(), ^id(id<NSObject> element) {
return element;
})];
NSString *defaultValue = [RCTConvert NSString:args.defaultValue()];
NSString *cancelButtonKey = [RCTConvert NSString:args.cancelButtonKey()];
NSString *destructiveButtonKey = [RCTConvert NSString:args.destructiveButtonKey()];
UIKeyboardType keyboardType = [RCTConvert UIKeyboardType:args.keyboardType()];
if (!title && !message) {
RCTLogError(@"Must specify either an alert title, or message, or both");
return;
}
if (buttons.count == 0) {
if (type == RCTAlertViewStyleDefault) {
buttons = @[ @{@"0" : RCTUIKitLocalizedString(@"OK")} ];
cancelButtonKey = @"0";
} else {
buttons = @[
@{@"0" : RCTUIKitLocalizedString(@"OK")},
@{@"1" : RCTUIKitLocalizedString(@"Cancel")},
];
cancelButtonKey = @"1";
}
}
iOS: Update RCTAlertManager to use new RCTAlertController (#29295) Summary: This should fix https://github.com/facebook/react-native/issues/29082 and https://github.com/facebook/react-native/issues/10471 Currently when an alert is being shown while a modal is being dismissed, it causes the alert not to show and In some cases it causes the UI to become unresponsive. I think this was caused by using RCTPresentedViewController to try and display the Alert the currently presented view. The View the Alert was going to be shown on is dismissed and the modal doesn't show. I implemented a new RCTAlertController to show the alert on top of the view, the modal being dismissed should now not interfere with the alert being shown. ## Changelog [iOS] [Fixed] - Fixed showing Alert while closing a Modal Pull Request resolved: https://github.com/facebook/react-native/pull/29295 Test Plan: To recreate the bug: 1. npx react-native init Test --version 0.63.0-rc.1 2. Paste the following code into App.js ```javascript /** * Sample React Native App * https://github.com/facebook/react-native * * format * flow strict-local */ import React from 'react'; import { SafeAreaView, StyleSheet, View, Text, StatusBar, Modal, Alert } from 'react-native'; const App: () => React$Node = () => { const [visible, setVisible] = React.useState(false) const onShowModal = () => { setVisible(true) } onCloseBroken = () => { setVisible(false) Alert.alert('Alert', 'Alert won\'t show') } onCloseWorking = () => { setVisible(false) setTimeout(() => Alert.alert('Alert', 'Works fine'), 10) } return ( <> <StatusBar barStyle="dark-content" /> <SafeAreaView style={styles.container}> <Text onPress={onShowModal}>Show modal</Text> </SafeAreaView> <Modal animationType="fade" visible={visible} onRequestClose={onCloseWorking} > <View style={styles.container}> <Text onPress={onCloseBroken}>Close modal immediately</Text> <Text onPress={onCloseWorking}>Close modal with delay</Text> </View> </Modal> </> ) } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'space-around', }, }) export default App ``` 3. cd Test && npx react-native run-ios 4. Show the modal and click the `Close modal immediately` button The first button doesn't show the alert, the second does because it gets rendered after the modal view is dismissed. After this commit, the alert always shows on top of every view properly. You can test by pointing the react native package to my branch by modifying the package json file like this ``` "react-native": "https://github.com/devon94/react-native.git#fix-ios-modal" ``` I was unable to reproduce the case where it causes the UI to be responsive in the test app but was able to reproduce it in our react native app at work. I can provide a video later if needed but the code is too complex to simplify into a test case. Reviewed By: sammy-SC Differential Revision: D22783371 Pulled By: PeteTheHeat fbshipit-source-id: 3e359645c610074ea855ee5686c59bdb9d6b696b
2020-08-07 02:18:31 +03:00
RCTAlertController *alertController = [RCTAlertController alertControllerWithTitle:title
message:nil
preferredStyle:UIAlertControllerStyleAlert];
switch (type) {
case RCTAlertViewStylePlainTextInput: {
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.secureTextEntry = NO;
textField.text = defaultValue;
textField.keyboardType = keyboardType;
}];
break;
}
case RCTAlertViewStyleSecureTextInput: {
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.placeholder = RCTUIKitLocalizedString(@"Password");
textField.secureTextEntry = YES;
textField.text = defaultValue;
textField.keyboardType = keyboardType;
}];
break;
}
case RCTAlertViewStyleLoginAndPasswordInput: {
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.placeholder = RCTUIKitLocalizedString(@"Login");
textField.text = defaultValue;
textField.keyboardType = keyboardType;
}];
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.placeholder = RCTUIKitLocalizedString(@"Password");
textField.secureTextEntry = YES;
}];
break;
Refactored module access to allow for lazy loading Summary: public The `bridge.modules` dictionary provides access to all native modules, but this API requires that every module is initialized in advance so that any module can be accessed. This diff introduces a better API that will allow modules to be initialized lazily as they are needed, and deprecates `bridge.modules` (modules that use it will still work, but should be rewritten to use `bridge.moduleClasses` or `-[bridge moduleForName/Class:` instead. The rules are now as follows: * Any module that overrides `init` or `setBridge:` will be initialized on the main thread when the bridge is created * Any module that implements `constantsToExport:` will be initialized later when the config is exported (the module itself will be initialized on a background queue, but `constantsToExport:` will still be called on the main thread. * All other modules will be initialized lazily when a method is first called on them. These rules may seem slightly arcane, but they have the advantage of not violating any assumptions that may have been made by existing code - any module written under the original assumption that it would be initialized synchronously on the main thread when the bridge is created should still function exactly the same, but modules that avoid overriding `init` or `setBridge:` will now be loaded lazily. I've rewritten most of the standard modules to take advantage of this new lazy loading, with the following results: Out of the 65 modules included in UIExplorer: * 16 are initialized on the main thread when the bridge is created * A further 8 are initialized when the config is exported to JS * The remaining 41 will be initialized lazily on-demand Reviewed By: jspahrsummers Differential Revision: D2677695 fb-gh-sync-id: 507ae7e9fd6b563e89292c7371767c978e928f33
2015-11-25 14:09:00 +03:00
}
case RCTAlertViewStyleDefault:
break;
}
alertController.message = message;
for (NSDictionary<NSString *, id> *button in buttons) {
if (button.count != 1) {
RCTLogError(@"Button definitions should have exactly one key.");
}
NSString *buttonKey = button.allKeys.firstObject;
NSString *buttonTitle = [RCTConvert NSString:button[buttonKey]];
UIAlertActionStyle buttonStyle = UIAlertActionStyleDefault;
if ([buttonKey isEqualToString:cancelButtonKey]) {
buttonStyle = UIAlertActionStyleCancel;
} else if ([buttonKey isEqualToString:destructiveButtonKey]) {
buttonStyle = UIAlertActionStyleDestructive;
}
iOS: Update RCTAlertManager to use new RCTAlertController (#29295) Summary: This should fix https://github.com/facebook/react-native/issues/29082 and https://github.com/facebook/react-native/issues/10471 Currently when an alert is being shown while a modal is being dismissed, it causes the alert not to show and In some cases it causes the UI to become unresponsive. I think this was caused by using RCTPresentedViewController to try and display the Alert the currently presented view. The View the Alert was going to be shown on is dismissed and the modal doesn't show. I implemented a new RCTAlertController to show the alert on top of the view, the modal being dismissed should now not interfere with the alert being shown. ## Changelog [iOS] [Fixed] - Fixed showing Alert while closing a Modal Pull Request resolved: https://github.com/facebook/react-native/pull/29295 Test Plan: To recreate the bug: 1. npx react-native init Test --version 0.63.0-rc.1 2. Paste the following code into App.js ```javascript /** * Sample React Native App * https://github.com/facebook/react-native * * format * flow strict-local */ import React from 'react'; import { SafeAreaView, StyleSheet, View, Text, StatusBar, Modal, Alert } from 'react-native'; const App: () => React$Node = () => { const [visible, setVisible] = React.useState(false) const onShowModal = () => { setVisible(true) } onCloseBroken = () => { setVisible(false) Alert.alert('Alert', 'Alert won\'t show') } onCloseWorking = () => { setVisible(false) setTimeout(() => Alert.alert('Alert', 'Works fine'), 10) } return ( <> <StatusBar barStyle="dark-content" /> <SafeAreaView style={styles.container}> <Text onPress={onShowModal}>Show modal</Text> </SafeAreaView> <Modal animationType="fade" visible={visible} onRequestClose={onCloseWorking} > <View style={styles.container}> <Text onPress={onCloseBroken}>Close modal immediately</Text> <Text onPress={onCloseWorking}>Close modal with delay</Text> </View> </Modal> </> ) } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'space-around', }, }) export default App ``` 3. cd Test && npx react-native run-ios 4. Show the modal and click the `Close modal immediately` button The first button doesn't show the alert, the second does because it gets rendered after the modal view is dismissed. After this commit, the alert always shows on top of every view properly. You can test by pointing the react native package to my branch by modifying the package json file like this ``` "react-native": "https://github.com/devon94/react-native.git#fix-ios-modal" ``` I was unable to reproduce the case where it causes the UI to be responsive in the test app but was able to reproduce it in our react native app at work. I can provide a video later if needed but the code is too complex to simplify into a test case. Reviewed By: sammy-SC Differential Revision: D22783371 Pulled By: PeteTheHeat fbshipit-source-id: 3e359645c610074ea855ee5686c59bdb9d6b696b
2020-08-07 02:18:31 +03:00
__weak RCTAlertController *weakAlertController = alertController;
[alertController
addAction:[UIAlertAction
actionWithTitle:buttonTitle
style:buttonStyle
handler:^(__unused UIAlertAction *action) {
switch (type) {
case RCTAlertViewStylePlainTextInput:
case RCTAlertViewStyleSecureTextInput:
callback(@[ buttonKey, [weakAlertController.textFields.firstObject text] ]);
[weakAlertController hide];
break;
case RCTAlertViewStyleLoginAndPasswordInput: {
NSDictionary<NSString *, NSString *> *loginCredentials = @{
@"login" : [weakAlertController.textFields.firstObject text],
@"password" : [weakAlertController.textFields.lastObject text]
};
callback(@[ buttonKey, loginCredentials ]);
[weakAlertController hide];
break;
}
case RCTAlertViewStyleDefault:
callback(@[ buttonKey ]);
[weakAlertController hide];
break;
}
}]];
}
Refactored module access to allow for lazy loading Summary: public The `bridge.modules` dictionary provides access to all native modules, but this API requires that every module is initialized in advance so that any module can be accessed. This diff introduces a better API that will allow modules to be initialized lazily as they are needed, and deprecates `bridge.modules` (modules that use it will still work, but should be rewritten to use `bridge.moduleClasses` or `-[bridge moduleForName/Class:` instead. The rules are now as follows: * Any module that overrides `init` or `setBridge:` will be initialized on the main thread when the bridge is created * Any module that implements `constantsToExport:` will be initialized later when the config is exported (the module itself will be initialized on a background queue, but `constantsToExport:` will still be called on the main thread. * All other modules will be initialized lazily when a method is first called on them. These rules may seem slightly arcane, but they have the advantage of not violating any assumptions that may have been made by existing code - any module written under the original assumption that it would be initialized synchronously on the main thread when the bridge is created should still function exactly the same, but modules that avoid overriding `init` or `setBridge:` will now be loaded lazily. I've rewritten most of the standard modules to take advantage of this new lazy loading, with the following results: Out of the 65 modules included in UIExplorer: * 16 are initialized on the main thread when the bridge is created * A further 8 are initialized when the config is exported to JS * The remaining 41 will be initialized lazily on-demand Reviewed By: jspahrsummers Differential Revision: D2677695 fb-gh-sync-id: 507ae7e9fd6b563e89292c7371767c978e928f33
2015-11-25 14:09:00 +03:00
if (!_alertControllers) {
_alertControllers = [NSHashTable weakObjectsHashTable];
}
[_alertControllers addObject:alertController];
Fixes alert view block first responder (#23240) Summary: Fixes #23076 , the reason is `blur()` is managed by `UIManager`, `UIManager` maintains all operations and execute them each `batchDidComplete`, which means every time `JS` finish callback native , but `Alert` module would call directly, this mess up the order of method call, for example like below, even `this.$input.blur()` is called before `Alert.alert()`, but in native side, `Alert.alert()` is called before `this.$input.blur()`. ``` <TextInput style={{ borderWidth: 1 }} ref={$input => this.$input = $input} /> <Button title="Show Alert" onPress={() => { // // `blur` works if using without `Alert` this.$input && this.$input.blur() // // `blur` is not working Alert.alert('show alert', 'desc', [ { text: 'cancel', style: 'cancel' }, { text: 'show', onPress: () => { }}, ]) }} /> ``` [iOS] [Fixed] - Fixes alert view block first responder After fix, example like below, `blur` can works. ``` import * as React from 'react'; import { TextInput, View, Alert, Button } from 'react-native'; export default class App extends React.Component { render() { return ( <View style={{ flex: 1, justifyContent: 'center' }}> <TextInput style={{ borderWidth: 1 }} ref={$input => this.$input = $input} /> <Button title="Show Alert" onPress={() => { this.$input && this.$input.blur() Alert.alert('show alert', 'desc', [ { text: 'cancel', style: 'cancel' }, { text: 'show', onPress: () => { }}, ]) }} /> </View> ); } } ``` Pull Request resolved: https://github.com/facebook/react-native/pull/23240 Differential Revision: D13915920 Pulled By: cpojer fbshipit-source-id: fe1916fcb5913e2b8128d045a6364c5e3d39c516
2019-02-01 14:48:02 +03:00
dispatch_async(dispatch_get_main_queue(), ^{
iOS: Update RCTAlertManager to use new RCTAlertController (#29295) Summary: This should fix https://github.com/facebook/react-native/issues/29082 and https://github.com/facebook/react-native/issues/10471 Currently when an alert is being shown while a modal is being dismissed, it causes the alert not to show and In some cases it causes the UI to become unresponsive. I think this was caused by using RCTPresentedViewController to try and display the Alert the currently presented view. The View the Alert was going to be shown on is dismissed and the modal doesn't show. I implemented a new RCTAlertController to show the alert on top of the view, the modal being dismissed should now not interfere with the alert being shown. ## Changelog [iOS] [Fixed] - Fixed showing Alert while closing a Modal Pull Request resolved: https://github.com/facebook/react-native/pull/29295 Test Plan: To recreate the bug: 1. npx react-native init Test --version 0.63.0-rc.1 2. Paste the following code into App.js ```javascript /** * Sample React Native App * https://github.com/facebook/react-native * * format * flow strict-local */ import React from 'react'; import { SafeAreaView, StyleSheet, View, Text, StatusBar, Modal, Alert } from 'react-native'; const App: () => React$Node = () => { const [visible, setVisible] = React.useState(false) const onShowModal = () => { setVisible(true) } onCloseBroken = () => { setVisible(false) Alert.alert('Alert', 'Alert won\'t show') } onCloseWorking = () => { setVisible(false) setTimeout(() => Alert.alert('Alert', 'Works fine'), 10) } return ( <> <StatusBar barStyle="dark-content" /> <SafeAreaView style={styles.container}> <Text onPress={onShowModal}>Show modal</Text> </SafeAreaView> <Modal animationType="fade" visible={visible} onRequestClose={onCloseWorking} > <View style={styles.container}> <Text onPress={onCloseBroken}>Close modal immediately</Text> <Text onPress={onCloseWorking}>Close modal with delay</Text> </View> </Modal> </> ) } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'space-around', }, }) export default App ``` 3. cd Test && npx react-native run-ios 4. Show the modal and click the `Close modal immediately` button The first button doesn't show the alert, the second does because it gets rendered after the modal view is dismissed. After this commit, the alert always shows on top of every view properly. You can test by pointing the react native package to my branch by modifying the package json file like this ``` "react-native": "https://github.com/devon94/react-native.git#fix-ios-modal" ``` I was unable to reproduce the case where it causes the UI to be responsive in the test app but was able to reproduce it in our react native app at work. I can provide a video later if needed but the code is too complex to simplify into a test case. Reviewed By: sammy-SC Differential Revision: D22783371 Pulled By: PeteTheHeat fbshipit-source-id: 3e359645c610074ea855ee5686c59bdb9d6b696b
2020-08-07 02:18:31 +03:00
[alertController show:YES completion:nil];
Fixes alert view block first responder (#23240) Summary: Fixes #23076 , the reason is `blur()` is managed by `UIManager`, `UIManager` maintains all operations and execute them each `batchDidComplete`, which means every time `JS` finish callback native , but `Alert` module would call directly, this mess up the order of method call, for example like below, even `this.$input.blur()` is called before `Alert.alert()`, but in native side, `Alert.alert()` is called before `this.$input.blur()`. ``` <TextInput style={{ borderWidth: 1 }} ref={$input => this.$input = $input} /> <Button title="Show Alert" onPress={() => { // // `blur` works if using without `Alert` this.$input && this.$input.blur() // // `blur` is not working Alert.alert('show alert', 'desc', [ { text: 'cancel', style: 'cancel' }, { text: 'show', onPress: () => { }}, ]) }} /> ``` [iOS] [Fixed] - Fixes alert view block first responder After fix, example like below, `blur` can works. ``` import * as React from 'react'; import { TextInput, View, Alert, Button } from 'react-native'; export default class App extends React.Component { render() { return ( <View style={{ flex: 1, justifyContent: 'center' }}> <TextInput style={{ borderWidth: 1 }} ref={$input => this.$input = $input} /> <Button title="Show Alert" onPress={() => { this.$input && this.$input.blur() Alert.alert('show alert', 'desc', [ { text: 'cancel', style: 'cancel' }, { text: 'show', onPress: () => { }}, ]) }} /> </View> ); } } ``` Pull Request resolved: https://github.com/facebook/react-native/pull/23240 Differential Revision: D13915920 Pulled By: cpojer fbshipit-source-id: fe1916fcb5913e2b8128d045a6364c5e3d39c516
2019-02-01 14:48:02 +03:00
});
}
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-17 03:23:39 +03:00
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
(const facebook::react::ObjCTurboModule::InitParams &)params
{
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-17 03:23:39 +03:00
return std::make_shared<facebook::react::NativeAlertManagerSpecJSI>(params);
}
@end
Class RCTAlertManagerCls(void)
{
return RCTAlertManager.class;
}