From 112e3767ceae83e9034c25a0358949a20b379358 Mon Sep 17 00:00:00 2001 From: Mehdi Mulani Date: Tue, 20 Jun 2017 18:42:46 -0700 Subject: [PATCH] Fix crash in AccessibilityManager Summary: Fix this crash by making sure the RCTDeviceInfo is doing things on the main thread. This fixes #14043. Reviewed By: ashwinb Differential Revision: D5286746 fbshipit-source-id: cce3426a6e7e7221cff82f8bca663d9a060dd358 --- IntegrationTests/AccessibilityManagerTest.js | 52 +++++++++++++++++++ IntegrationTests/IntegrationTestsApp.js | 1 + .../RNTesterIntegrationTests.m | 1 + React/Modules/RCTDeviceInfo.m | 23 +++++--- 4 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 IntegrationTests/AccessibilityManagerTest.js diff --git a/IntegrationTests/AccessibilityManagerTest.js b/IntegrationTests/AccessibilityManagerTest.js new file mode 100644 index 00000000000000..8f82374baa18e6 --- /dev/null +++ b/IntegrationTests/AccessibilityManagerTest.js @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @flow + * @providesModule AccessibilityManagerTest + */ +'use strict'; + +const React = require('react'); +const ReactNative = require('react-native'); +const { View } = ReactNative; +const RCTDeviceEventEmitter = require('RCTDeviceEventEmitter'); +const { + TestModule, + AccessibilityManager, +} = ReactNative.NativeModules; + + +class AccessibilityManagerTest extends React.Component { + componentDidMount() { + AccessibilityManager.setAccessibilityContentSizeMultipliers({ + 'extraSmall': 1.0, + 'small': 2.0, + 'medium': 3.0, + 'large': 4.0, + 'extraLarge': 5.0, + 'extraExtraLarge': 6.0, + 'extraExtraExtraLarge': 7.0, + 'accessibilityMedium': 8.0, + 'accessibilityLarge': 9.0, + 'accessibilityExtraLarge': 10.0, + 'accessibilityExtraExtraLarge': 11.0, + 'accessibilityExtraExtraExtraLarge': 12.0, + }); + RCTDeviceEventEmitter.addListener('didUpdateDimensions', update => { + TestModule.markTestPassed(update.window.fontScale === 4.0); + }); + } + + render(): React.Element { + return ; + } +} + +AccessibilityManagerTest.displayName = 'AccessibilityManagerTest'; + +module.exports = AccessibilityManagerTest; diff --git a/IntegrationTests/IntegrationTestsApp.js b/IntegrationTests/IntegrationTestsApp.js index 5977188f76830d..c2a417fa73248e 100644 --- a/IntegrationTests/IntegrationTestsApp.js +++ b/IntegrationTests/IntegrationTestsApp.js @@ -35,6 +35,7 @@ var TESTS = [ require('./PromiseTest'), require('./SyncMethodTest'), require('./WebSocketTest'), + require('./AccessibilityManagerTest'), ]; TESTS.forEach( diff --git a/RNTester/RNTesterIntegrationTests/RNTesterIntegrationTests.m b/RNTester/RNTesterIntegrationTests/RNTesterIntegrationTests.m index 3840cad8e78c34..a4633dc0063fc7 100644 --- a/RNTester/RNTesterIntegrationTests/RNTesterIntegrationTests.m +++ b/RNTester/RNTesterIntegrationTests/RNTesterIntegrationTests.m @@ -74,6 +74,7 @@ - (void)testTheTester_ExpectError RCT_TEST(SyncMethodTest) RCT_TEST(PromiseTest) RCT_TEST_ONLY_WITH_PACKAGER(WebSocketTest) +RCT_TEST(AccessibilityManagerTest) @end diff --git a/React/Modules/RCTDeviceInfo.m b/React/Modules/RCTDeviceInfo.m index ef4b71a79ee411..b895ef12d97c62 100644 --- a/React/Modules/RCTDeviceInfo.m +++ b/React/Modules/RCTDeviceInfo.m @@ -67,7 +67,7 @@ - (void)setBridge:(RCTBridge *)bridge - (void)invalidate { - dispatch_async(dispatch_get_main_queue(), ^{ + RCTExecuteOnMainQueue(^{ self->_bridge = nil; [[NSNotificationCenter defaultCenter] removeObserver:self]; }); @@ -82,18 +82,30 @@ - (void)invalidate - (void)didReceiveNewContentSizeMultiplier { - // Report the event across the bridge. + RCTBridge *bridge = _bridge; + RCTExecuteOnMainQueue(^{ + // Report the event across the bridge. #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [_bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions" - body:RCTExportedDimensions(_bridge)]; + [bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions" + body:RCTExportedDimensions(bridge)]; #pragma clang diagnostic pop + }); } - - (void)interfaceOrientationDidChange { #if !TARGET_OS_TV + __weak typeof(self) weakSelf = self; + RCTExecuteOnMainQueue(^{ + [weakSelf _interfaceOrientationDidChange]; + }); +#endif +} + + +- (void)_interfaceOrientationDidChange +{ UIInterfaceOrientation nextOrientation = [RCTSharedApplication() statusBarOrientation]; // Update when we go from portrait to landscape, or landscape to portrait @@ -109,7 +121,6 @@ - (void)interfaceOrientationDidChange } _currentInterfaceOrientation = nextOrientation; -#endif }