From 7e61f433ef3919ac828aff3c22a7bf82acf80a08 Mon Sep 17 00:00:00 2001 From: Mike Grabowski Date: Wed, 8 Aug 2018 20:29:47 +0200 Subject: [PATCH 001/273] Remove babel preset (its already dependency anyway) and babelrc to use Metro defaults --- local-cli/init/init.js | 2 +- local-cli/templates/HelloWorld/_babelrc | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) delete mode 100644 local-cli/templates/HelloWorld/_babelrc diff --git a/local-cli/init/init.js b/local-cli/init/init.js index d7497a4a828476..30209bc9485507 100644 --- a/local-cli/init/init.js +++ b/local-cli/init/init.js @@ -99,7 +99,7 @@ function generateProject(destinationRoot, newProjectName, options) { }); } if (!options['skip-jest']) { - const jestDeps = `jest babel-jest babel-preset-react-native@^5 react-test-renderer@${reactVersion}`; + const jestDeps = `jest babel-jest react-test-renderer@${reactVersion}`; if (yarnVersion) { console.log('Adding Jest...'); execSync(`yarn add ${jestDeps} --dev --exact`, {stdio: 'inherit'}); diff --git a/local-cli/templates/HelloWorld/_babelrc b/local-cli/templates/HelloWorld/_babelrc deleted file mode 100644 index a9ce1369e617e9..00000000000000 --- a/local-cli/templates/HelloWorld/_babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["react-native"] -} From be136a000f34be52f383b53b1d5af924efa0a6d4 Mon Sep 17 00:00:00 2001 From: Lorenzo Sciandra Date: Mon, 13 Aug 2018 21:38:21 +0100 Subject: [PATCH 002/273] Revert "Remove babel preset (its already dependency anyway) and babelrc to use Metro defaults" This reverts commit 7e61f433ef3919ac828aff3c22a7bf82acf80a08. --- local-cli/init/init.js | 2 +- local-cli/templates/HelloWorld/_babelrc | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 local-cli/templates/HelloWorld/_babelrc diff --git a/local-cli/init/init.js b/local-cli/init/init.js index 30209bc9485507..d7497a4a828476 100644 --- a/local-cli/init/init.js +++ b/local-cli/init/init.js @@ -99,7 +99,7 @@ function generateProject(destinationRoot, newProjectName, options) { }); } if (!options['skip-jest']) { - const jestDeps = `jest babel-jest react-test-renderer@${reactVersion}`; + const jestDeps = `jest babel-jest babel-preset-react-native@^5 react-test-renderer@${reactVersion}`; if (yarnVersion) { console.log('Adding Jest...'); execSync(`yarn add ${jestDeps} --dev --exact`, {stdio: 'inherit'}); diff --git a/local-cli/templates/HelloWorld/_babelrc b/local-cli/templates/HelloWorld/_babelrc new file mode 100644 index 00000000000000..a9ce1369e617e9 --- /dev/null +++ b/local-cli/templates/HelloWorld/_babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["react-native"] +} From e5ec57d807dd402f610cfa8ee1dd6b7dbf29d061 Mon Sep 17 00:00:00 2001 From: Tom Atterton Date: Mon, 6 Aug 2018 12:14:37 -0700 Subject: [PATCH 003/273] Ignore DevDependencies when generating template. (#20542) Summary: Regarding [Add devDependenices support for templates](https://github.com/facebook/react-native/commit/c4ab03a18e75e6ed55444b5d86f3ceee435b9a78). Once a project is created using the custom template command with devDependencies inside, the devDependenices.json file is also copied to the new projects directory. By adding this to the ignore paths we stop the devDependenices being copied into the new projects directory. Pull Request resolved: https://github.com/facebook/react-native/pull/20542 Differential Revision: D9182795 Pulled By: hramos fbshipit-source-id: 543c8ca67612a981c22fc83c8d54a25ddc0ca5fc --- local-cli/generator/templates.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local-cli/generator/templates.js b/local-cli/generator/templates.js index 17e4379a72b359..183bdd6438f1fa 100644 --- a/local-cli/generator/templates.js +++ b/local-cli/generator/templates.js @@ -171,7 +171,7 @@ function createFromRemoteTemplate( // only for publishing the template to npm. // We want to ignore this dummy file, otherwise it would overwrite // our project's package.json file. - ignorePaths: ['package.json', 'dependencies.json'], + ignorePaths: ['package.json', 'dependencies.json','devDependencies.json'], }); installTemplateDependencies(templatePath, yarnVersion); installTemplateDevDependencies(templatePath, yarnVersion); From e9b5753eb4b7fbe1bcfca53b7baeb61e324d8049 Mon Sep 17 00:00:00 2001 From: Tvrqvoise Date: Mon, 6 Aug 2018 12:23:45 -0700 Subject: [PATCH 004/273] Add support for linking scoped packages (#18766) (#19828) Summary: Currently, when the cli tries to determine the package name, it accidentally trims out the entire package name. This makes it appear to the rest of the program as if `react-native link The controller you requested could not be found./my-package` was just `react-native link`. This adds a little regex to prevent that from happening, so that scopes can be passed as parts of packages. Fixes #18766 Pull Request resolved: https://github.com/facebook/react-native/pull/19828 Differential Revision: D8704742 Pulled By: hramos fbshipit-source-id: d8183f9b55e8656b8a0acae842e1361a1f428102 --- local-cli/core/index.js | 4 +--- local-cli/link/__tests__/link.spec.js | 14 ++++++++++++++ local-cli/link/link.js | 4 ++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/local-cli/core/index.js b/local-cli/core/index.js index 47d099e74ee9ec..1a9ab03db36031 100644 --- a/local-cli/core/index.js +++ b/local-cli/core/index.js @@ -106,9 +106,7 @@ const defaultRNConfig = { getDependencyConfig(packageName: string) { const platforms = this.getPlatformConfig(); const folder = path.join(process.cwd(), 'node_modules', packageName); - const rnpm = getRNPMConfig( - path.join(process.cwd(), 'node_modules', packageName), - ); + const rnpm = getRNPMConfig(folder); let config = Object.assign({}, rnpm, { assets: findAssets(folder, rnpm.assets), diff --git a/local-cli/link/__tests__/link.spec.js b/local-cli/link/__tests__/link.spec.js index 9cbe601f2fb474..b44bf22b1eb153 100644 --- a/local-cli/link/__tests__/link.spec.js +++ b/local-cli/link/__tests__/link.spec.js @@ -49,6 +49,20 @@ describe('link', () => { }); }); + it('should accept the name of a dependency with a scope / tag', async () => { + const config = { + getPlatformConfig: () => ({ios: {}, android: {}}), + getProjectConfig: () => ({assets: []}), + getDependencyConfig: sinon.stub().returns({assets: [], commands: {}}), + }; + + const link = require('../link').func; + await link(['@scope/something@latest'], config); + expect( + config.getDependencyConfig.calledWith('@scope/something'), + ).toBeTruthy(); + }); + it('should register native module when android/ios projects are present', done => { const registerNativeModule = sinon.stub(); const dependencyConfig = {android: {}, ios: {}, assets: [], commands: {}}; diff --git a/local-cli/link/link.js b/local-cli/link/link.js index 892e4f71063bc1..50d7f16e99b21f 100644 --- a/local-cli/link/link.js +++ b/local-cli/link/link.js @@ -143,9 +143,9 @@ function link(args: Array, config: RNConfig) { } let packageName = args[0]; - // Check if install package by specific version (eg. package@latest) + // Trim the version / tag out of the package name (eg. package@latest) if (packageName !== undefined) { - packageName = packageName.split('@')[0]; + packageName = packageName.replace(/^(.+?)(@.+?)$/gi, '$1'); } const dependencies = getDependencyConfig( From 8954897948626f02aff16c5267866f5377050007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Mon, 6 Aug 2018 12:59:41 -0700 Subject: [PATCH 005/273] Consolidate e2e steps and run Detox tests before e2e (#20550) Summary: Run Detox before the flaky e2e iOS tests in order to get better signal. Pull Request resolved: https://github.com/facebook/react-native/pull/20550 Differential Revision: D9183655 Pulled By: hramos fbshipit-source-id: e499daad86249961cd6d0b8fc22c846392622056 --- .circleci/config.yml | 130 +++++++++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 60 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d80fd6aaf97b02..fd5b53d03059d9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -128,10 +128,6 @@ aliases: echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list sudo apt-get update && sudo apt-get install yarn - - &install-node-dependencies - | - npm install --no-package-lock --no-spin --no-progress - - &install-buck name: Install BUCK command: | @@ -147,13 +143,6 @@ aliases: mkdir -p ~/react-native/tooling/junit cp -R ~/okbuck/tooling/junit/* ~/react-native/tooling/junit/. - - - &install-node - name: Install Node - command: | - curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - - sudo apt-get install -y nodejs - - &create-ndk-directory name: Create Android NDK Directory command: | @@ -194,17 +183,11 @@ aliases: # eslint sometimes runs into trouble generating the reports - &run-lint-checks name: Lint code - command: | - if [ $((0 % CIRCLE_NODE_TOTAL)) -eq "$CIRCLE_NODE_INDEX" ]; then - scripts/circleci/exec_swallow_error.sh yarn lint --format junit -o ~/react-native/reports/junit/eslint/results.xml - fi + command: scripts/circleci/exec_swallow_error.sh yarn lint --format junit -o ~/react-native/reports/junit/eslint/results.xml - &run-flow-checks name: Check for errors in code using Flow - command: | - if [ $((0 % CIRCLE_NODE_TOTAL)) -eq "$CIRCLE_NODE_INDEX" ]; then - yarn flow check - fi + command: yarn flow check - &run-sanity-checks name: Sanity checks @@ -282,35 +265,45 @@ aliases: mkdir -p ~/react-native/reports/junit/ mkdir -p ~/react-native/reports/outputs/ + - &brew-install-watchman + name: Install Watchman + command: | + brew install watchman + touch .watchmanconfig + - &boot-simulator-iphone + name: Boot iPhone Simulator + command: xcrun simctl boot "iPhone 5s" || true + + - &boot-simulator-iphone-with-parallelism name: Boot iPhone Simulator command: | if [ $((0 % CIRCLE_NODE_TOTAL)) -eq "$CIRCLE_NODE_INDEX" ]; then xcrun simctl boot "iPhone 5s" || true fi - - &boot-simulator-appletv + - &boot-simulator-appletv-with-parallelism name: Boot Apple TV Simulator command: | if [ $((1 % CIRCLE_NODE_TOTAL)) -eq "$CIRCLE_NODE_INDEX" ]; then xcrun simctl boot "Apple TV" || true fi - - &run-objc-ios-tests + - &run-objc-ios-tests-with-parallelism name: iOS Test Suite command: | if [ $((0 % CIRCLE_NODE_TOTAL)) -eq "$CIRCLE_NODE_INDEX" ]; then ./scripts/objc-test-ios.sh test fi - - &run-objc-tvos-tests + - &run-objc-tvos-tests-with-parallelism name: tvOS Test Suite command: | if [ $((1 % CIRCLE_NODE_TOTAL)) -eq "$CIRCLE_NODE_INDEX" ]; then ./scripts/objc-test-tvos.sh test fi - - &run-podspec-tests + - &run-podspec-tests-with-parallelism name: Test CocoaPods command: | if [ $((2 % CIRCLE_NODE_TOTAL)) -eq "$CIRCLE_NODE_INDEX" ]; then @@ -321,6 +314,29 @@ aliases: name: End-to-End Test Suite command: node ./scripts/run-ci-e2e-tests.js --android --ios --tvos --js --retries 3; + - &install-node-8 + name: Install Node 8 + command: | + echo 'export PATH=/usr/local/opt/node@8/bin:$PATH' >> $BASH_ENV + source $BASH_ENV + brew install node@8 + brew link node@8 + node -v + + - &install-apple-simulator-utils + name: Install Apple Simulator Utilities + command: | + brew tap wix/brew + brew install applesimutils + + - &build-ios-app-e2e + name: Build iOS App for Simulator + command: yarn run build-ios-e2e + + - &run-ios-detox-tests + name: Run Detox Tests + command: yarn run test-ios-e2e + - &run-objc-ios-e2e-tests name: iOS End-to-End Test Suite command: | @@ -425,56 +441,45 @@ jobs: - attach_workspace: at: ~/react-native - - run: *boot-simulator-iphone - - run: *boot-simulator-appletv - - run: brew install watchman + - run: *boot-simulator-iphone-with-parallelism + - run: *boot-simulator-appletv-with-parallelism + - run: *brew-install-watchman - - run: *run-objc-ios-tests - - run: *run-objc-tvos-tests - - run: *run-podspec-tests + - run: *run-objc-ios-tests-with-parallelism + - run: *run-objc-tvos-tests-with-parallelism + - run: *run-podspec-tests-with-parallelism - store_test_results: path: ~/react-native/reports/junit - # Runs end to end tests - test_end_to_end: + # Runs end to end tests (Objective-C) + test_objc_end_to_end: <<: *macos_defaults steps: - attach_workspace: at: ~/react-native - - run: - name: Boot iOS Simulator - command: xcrun simctl boot "iPhone 5s" || true + - run: *boot-simulator-iphone - - run: - name: Configure Environment Variables - command: | - echo 'export PATH=/usr/local/opt/node@8/bin:$PATH' >> $BASH_ENV - source $BASH_ENV + - run: *run-objc-ios-e2e-tests - - run: - name: Install Node 8 - command: | - brew install node@8 - brew link node@8 - node -v + - store_test_results: + path: ~/react-native/reports/junit - - run: *run-objc-ios-e2e-tests + # Runs end to end tests (Detox) + test_detox_end_to_end: + <<: *macos_defaults + steps: + - attach_workspace: + at: ~/react-native - - run: - name: Install Apple Simulator Utilities - command: | - brew tap wix/brew - brew install applesimutils + - run: *boot-simulator-iphone - - run: - name: Build iOS App for Simulator - command: yarn run build-ios-e2e + - run: *install-node-8 + - run: *install-apple-simulator-utils + - run: *build-ios-app-e2e - - run: - name: Run Detox Tests - command: yarn run test-ios-e2e + - run: *run-ios-detox-tests - store_test_results: path: ~/react-native/reports/junit @@ -670,11 +675,17 @@ workflows: - checkout_code # End-to-end tests - - test_end_to_end: + - test_objc_end_to_end: filters: *filter-ignore-gh-pages requires: - checkout_code + - test_detox_end_to_end: + filters: *filter-ignore-gh-pages + requires: + - checkout_code + + # Only runs on vX.X.X tags if all tests are green - publish_npm_package: filters: @@ -687,8 +698,7 @@ workflows: - test_javascript - test_objc - test_android - - test_end_to_end - - analyze + - test_objc_end_to_end # Only runs on PRs analyze: From 8965e0ca1849c7441a89f012b1af3a3ca8130e77 Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Mon, 6 Aug 2018 14:56:11 -0700 Subject: [PATCH 006/273] Un-deprecate TextInput.State.focusTextInput and TextInput.State.blurTextInput (#20326) Summary: In https://github.com/facebook/react-native/pull/18936 we decided to deprecate `focusTextInput` and `blurTextInput` but since then I found a valid use case for it that is pretty much impossible to implement otherwise. React Navigation uses it to blur / re-focus the input during the swipe back gesture. Blur can be done with Keyboard.dismiss but without this api we cannot re-focus the text field that was focused if the swipe back gesture is cancelled. See https://github.com/react-navigation/react-navigation/blob/master/src/navigators/createKeyboardAwareNavigator.js#L21-L34 I think it is best to just bring back this api. Pull Request resolved: https://github.com/facebook/react-native/pull/20326 Differential Revision: D9182810 Pulled By: hramos fbshipit-source-id: 3740421ffafb8f814522d15788f3466324177c16 --- Libraries/Components/TextInput/TextInput.js | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index 80dcb8ecf182a2..178821b3ad7042 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -326,18 +326,8 @@ const TextInput = createReactClass({ statics: { State: { currentlyFocusedField: TextInputState.currentlyFocusedField, - focusTextInput: (textFieldID: ?number) => { - console.warn( - '`focusTextInput` is deprecated, use the `focus` method of the `TextInput` ref instead.', - ); - TextInputState.focusTextInput(textFieldID); - }, - blurTextInput: (textFieldID: ?number) => { - console.warn( - '`blurTextInput` is deprecated, use `Keyboard.dismiss` or the `blur` method of the `TextInput` ref.', - ); - TextInputState.blurTextInput(textFieldID); - }, + focusTextInput: TextInputState.focusTextInput, + blurTextInput: TextInputState.blurTextInput, }, }, propTypes: { From 770d08b9897c9d95dd63f1256a3835bca1c30f77 Mon Sep 17 00:00:00 2001 From: Mayank Patke Date: Tue, 7 Aug 2018 15:56:04 -0700 Subject: [PATCH 007/273] v0.78 in fbsource Summary: The controller you requested could not be found. Reviewed By: pakoito Differential Revision: D9174188 fbshipit-source-id: 4ec9ef5b6f802964a83b6bc0bd29db7f47b37c21 --- .flowconfig | 2 +- local-cli/templates/HelloWorld/_flowconfig | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.flowconfig b/.flowconfig index 78e4e1976b8b7b..9f76ca39858e74 100644 --- a/.flowconfig +++ b/.flowconfig @@ -100,4 +100,4 @@ untyped-import untyped-type-import [version] -^0.77.0 +^0.78.0 diff --git a/local-cli/templates/HelloWorld/_flowconfig b/local-cli/templates/HelloWorld/_flowconfig index 5e726a323d1ecb..1043c82d706e48 100644 --- a/local-cli/templates/HelloWorld/_flowconfig +++ b/local-cli/templates/HelloWorld/_flowconfig @@ -67,4 +67,4 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError [version] -^0.77.0 +^0.78.0 diff --git a/package.json b/package.json index 223d4e2b13168c..45bfb4886043f7 100644 --- a/package.json +++ b/package.json @@ -215,7 +215,7 @@ "eslint-plugin-prettier": "2.6.0", "eslint-plugin-react": "7.8.2", "eslint-plugin-react-native": "^3.2.1", - "flow-bin": "^0.77.0", + "flow-bin": "^0.78.0", "jest": "23.4.1", "jest-junit": "5.1.0", "prettier": "1.13.6", From c7d17766b467f6080d77d03d62383b23f4f5681a Mon Sep 17 00:00:00 2001 From: Joshua Wang Date: Tue, 7 Aug 2018 19:39:05 -0700 Subject: [PATCH 008/273] Update template to Xcode 9.4 and fix project settings warnings (#19626) Summary: Motivation: Fix Xcode Project Settings Warnings ![screenshot 2018-06-08 10 58 23](https://user-images.githubusercontent.com/5353594/41173274-1a4fbb3e-6b0b-11e8-973b-8290794a4f8b.png) Should still build and pass all tests since project settings changes should be safe changes. No documentation change is required [IOS][MINOR][XcodeProjs] Upgraded Project settings to be compatible with Xcode 9.4 Pull Request resolved: https://github.com/facebook/react-native/pull/19626 Differential Revision: D9211230 Pulled By: hramos fbshipit-source-id: ef8692871bffbdb5dd0214f65220fd171c203c6c --- .../Sample/Sample.xcodeproj/project.pbxproj | 25 +++++++++++++- .../ios/HelloWorld.xcodeproj/project.pbxproj | 34 ++++++++++++++++--- .../xcschemes/HelloWorld-tvOS.xcscheme | 2 +- .../xcschemes/HelloWorld.xcscheme | 2 +- .../HelloWorld/ios/HelloWorld/Info.plist | 4 ++- .../HelloWorld/ios/HelloWorldTests/Info.plist | 2 +- 6 files changed, 60 insertions(+), 9 deletions(-) diff --git a/Libraries/Sample/Sample.xcodeproj/project.pbxproj b/Libraries/Sample/Sample.xcodeproj/project.pbxproj index b0fa1f7b34ac54..7200a72610119f 100644 --- a/Libraries/Sample/Sample.xcodeproj/project.pbxproj +++ b/Libraries/Sample/Sample.xcodeproj/project.pbxproj @@ -85,7 +85,7 @@ 58B511D31A9E6C8500147676 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0610; + LastUpgradeCheck = 0940; ORGANIZATIONNAME = Facebook; TargetAttributes = { 58B511DA1A9E6C8500147676 = { @@ -130,19 +130,31 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -170,19 +182,30 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; diff --git a/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj b/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj index 7346f2749ea6ae..15cf73e72a098a 100644 --- a/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj +++ b/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; }; 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; }; 00E356F31AD99517003FC87E /* HelloWorldTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* HelloWorldTests.m */; }; + 11D1A2F320CAFA9E000508D9 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; }; 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; }; 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; }; 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; }; @@ -35,7 +36,6 @@ 2D16E6881FA4F8E400B85C8A /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D16E6891FA4F8E400B85C8A /* libReact.a */; }; 2DCD954D1E0B4F2C00145EB5 /* HelloWorldTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* HelloWorldTests.m */; }; 2DF0FFEE2056DD460020B375 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3EA31DF850E9000B6D8A /* libReact.a */; }; - 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; }; 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */; }; /* End PBXBuildFile section */ @@ -359,9 +359,8 @@ buildActionMask = 2147483647; files = ( ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */, - 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */, + 11D1A2F320CAFA9E000508D9 /* libRCTAnimation.a in Frameworks */, 146834051AC3E58100842450 /* libReact.a in Frameworks */, - 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */, 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */, 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */, 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */, @@ -685,7 +684,7 @@ 83CBB9F71A601CBA00E9B192 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0610; + LastUpgradeCheck = 0940; ORGANIZATIONNAME = Facebook; TargetAttributes = { 00E356ED1AD99517003FC87E = { @@ -1179,6 +1178,7 @@ "-ObjC", "-lc++", ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HelloWorld.app/HelloWorld"; }; @@ -1196,6 +1196,7 @@ "-ObjC", "-lc++", ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HelloWorld.app/HelloWorld"; }; @@ -1214,6 +1215,7 @@ "-ObjC", "-lc++", ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = HelloWorld; VERSIONING_SYSTEM = "apple-generic"; }; @@ -1231,6 +1233,7 @@ "-ObjC", "-lc++", ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = HelloWorld; VERSIONING_SYSTEM = "apple-generic"; }; @@ -1346,20 +1349,32 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -1387,13 +1402,23 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -1401,6 +1426,7 @@ ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; diff --git a/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/xcshareddata/xcschemes/HelloWorld-tvOS.xcscheme b/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/xcshareddata/xcschemes/HelloWorld-tvOS.xcscheme index f058c975222f79..a4c88796c96134 100644 --- a/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/xcshareddata/xcschemes/HelloWorld-tvOS.xcscheme +++ b/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/xcshareddata/xcschemes/HelloWorld-tvOS.xcscheme @@ -1,6 +1,6 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -24,6 +24,8 @@ 1 LSRequiresIPhoneOS + NSLocationWhenInUseUsageDescription + UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities diff --git a/local-cli/templates/HelloWorld/ios/HelloWorldTests/Info.plist b/local-cli/templates/HelloWorld/ios/HelloWorldTests/Info.plist index 886825ccc9bf0d..ba72822e8728ef 100644 --- a/local-cli/templates/HelloWorld/ios/HelloWorldTests/Info.plist +++ b/local-cli/templates/HelloWorld/ios/HelloWorldTests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName From cb02754ba9e78e89eee4779c6e7a80de1826ad00 Mon Sep 17 00:00:00 2001 From: Kevin Gozali Date: Tue, 7 Aug 2018 21:20:58 -0700 Subject: [PATCH 009/273] added small UI indicator for fabric-based surfaces Summary: To make debugging/testing easier, optionally display fabric label on the top-right of the surface if it's rendered on fabric mode. Reviewed By: mdvacca Differential Revision: D9206473 fbshipit-source-id: ef6f0396ff749f2a0415688b1cf4fe1a4b83124d --- Libraries/ReactNative/ReactFabricIndicator.js | 42 +++++++++++++++++++ Libraries/ReactNative/renderApplication.js | 5 +++ 2 files changed, 47 insertions(+) create mode 100644 Libraries/ReactNative/ReactFabricIndicator.js diff --git a/Libraries/ReactNative/ReactFabricIndicator.js b/Libraries/ReactNative/ReactFabricIndicator.js new file mode 100644 index 00000000000000..23b95f8c161a9c --- /dev/null +++ b/Libraries/ReactNative/ReactFabricIndicator.js @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow + */ + +'use strict'; + +const React = require('React'); +const StyleSheet = require('StyleSheet'); +const Text = require('Text'); +const View = require('View'); + +function ReactFabricIndicator(): React.Node { + return ( + + FABRIC + + ); +} + +const styles = StyleSheet.create({ + container: { + alignItems: 'center', + justifyContent: 'center', + backgroundColor: 'rgba(0,0,0, 0.25)', + position: 'absolute', + top: 0, + right: 0, + padding: 2, + }, + text: { + fontSize: 6, + color: '#ffffff', + }, +}); + +module.exports = ReactFabricIndicator; diff --git a/Libraries/ReactNative/renderApplication.js b/Libraries/ReactNative/renderApplication.js index 7d699f754651f0..193262fc677c16 100644 --- a/Libraries/ReactNative/renderApplication.js +++ b/Libraries/ReactNative/renderApplication.js @@ -12,6 +12,7 @@ const AppContainer = require('AppContainer'); const React = require('React'); +const ReactFabricIndicator = require('ReactFabricIndicator'); const invariant = require('fbjs/lib/invariant'); @@ -24,12 +25,16 @@ function renderApplication( rootTag: any, WrapperComponent?: ?React.ComponentType<*>, fabric?: boolean, + showFabricIndicator?: boolean, ) { invariant(rootTag, 'Expect to have a valid rootTag, instead got ', rootTag); let renderable = ( + {fabric === true && showFabricIndicator === true ? ( + + ) : null} ); From 9b7d6d6b87693a41aad2eb7e2afa35a33b47d5fb Mon Sep 17 00:00:00 2001 From: gengjiawen Date: Tue, 7 Aug 2018 21:34:36 -0700 Subject: [PATCH 010/273] switch to yarn in appveyor (#20566) Summary: switch to yarn to keep consistent. Windows android build pass: https://ci.appveyor.com/project/gengjiawen/react-native/build/job/xyof6052yg2uhnmw. pass all current ci. none [GENERAL] [INTERNAL] [CI] - switch to yarn. Pull Request resolved: https://github.com/facebook/react-native/pull/20566 Differential Revision: D9213415 Pulled By: hramos fbshipit-source-id: 35183c143f831e29aa0d0c0b90baacb6a7cd7837 --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 560abe5ed0803f..3d5c4336a652cd 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -32,8 +32,8 @@ install: - ps: Install-Product node $env:nodejs_version - node --version - - npm --version - - appveyor-retry npm install + - yarn --version + - appveyor-retry yarn install build_script: - gradlew.bat RNTester:android:app:assembleRelease From 86e6a048ef67f1a1128e273c55b4bbd824d91171 Mon Sep 17 00:00:00 2001 From: Ziqi Chen Date: Wed, 8 Aug 2018 00:50:37 -0700 Subject: [PATCH 011/273] added accessibilityHints implementation on Android Summary: Implemented a version of accessibility Hints on android by adding hint text to the end of contentDescription. There is already an existing prop on js and iOS implementation. Changes involve: * adding a prop on native android code for accessibilityHints * setting the accessibilityDelegate after the props are all loaded. * Instead of directly updating the accessibility delegate, the prop setters now update state by setting the values of the variables. Once all props are set, the accessibility delegate is set based on the props * BaseViewManager keeps track of whether or not accessibility props have been set * AccessibilityDelegateUtil keeps track of what the props have been set to. (Renamed AccessibilityRoleUtil to AccessibilityDelegateUtil) Currently, this is the easiest way of emulating the way accessibility hints work on iOS, and I think having an android counter part is better than having nothing. It's different from iOS in that it will announce the hint before the role, and also cannot be turned off. Ex: if I set the accessibility like this: ``` Tester ``` Talk back will read: `accessibility label, accessibility Hint, button, selected` In the future for next steps, I plan on investigating the process of making a second announcement after the first Reviewed By: achen1 Differential Revision: D9037226 fbshipit-source-id: 8d484e1114eb69aa5f5314b3755b351b8ea80b09 --- ...il.java => AccessibilityDelegateUtil.java} | 37 +++++++++++-------- .../react/uimanager/BaseViewManager.java | 28 +++++++++++++- .../main/res/views/uimanager/values/ids.xml | 7 ++++ .../java/com/facebook/react/uimanager/BUCK | 1 + 4 files changed, 57 insertions(+), 16 deletions(-) rename ReactAndroid/src/main/java/com/facebook/react/uimanager/{AccessibilityRoleUtil.java => AccessibilityDelegateUtil.java} (75%) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/AccessibilityRoleUtil.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/AccessibilityDelegateUtil.java similarity index 75% rename from ReactAndroid/src/main/java/com/facebook/react/uimanager/AccessibilityRoleUtil.java rename to ReactAndroid/src/main/java/com/facebook/react/uimanager/AccessibilityDelegateUtil.java index 1be25440cdf266..c834c85fd2cd69 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/AccessibilityRoleUtil.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/AccessibilityDelegateUtil.java @@ -23,7 +23,7 @@ * AccessibilityNodeInfo. */ -public class AccessibilityRoleUtil { +public class AccessibilityDelegateUtil { /** * These roles are defined by Google's TalkBack screen reader, and this list should be kept up to @@ -41,7 +41,9 @@ public enum AccessibilityRole { IMAGEBUTTON("android.widget.ImageView"), KEYBOARDKEY("android.inputmethodservice.Keyboard$Key"), TEXT("android.widget.ViewGroup"), - ADJUSTABLE("android.widget.SeekBar"); + ADJUSTABLE("android.widget.SeekBar"), + SUMMARY("android.widget.ViewGroup"), + HEADER("android.widget.ViewGroup"); @Nullable private final String mValue; @@ -64,11 +66,11 @@ public static AccessibilityRole fromValue(String value) { } } - private AccessibilityRoleUtil() { + private AccessibilityDelegateUtil() { // No instances } - public static void setRole(final View view, final AccessibilityRole role) { + public static void setDelegate(final View view) { // if a view already has an accessibility delegate, replacing it could cause problems, // so leave it alone. if (!ViewCompat.hasAccessibilityDelegate(view)) { @@ -79,7 +81,18 @@ public static void setRole(final View view, final AccessibilityRole role) { public void onInitializeAccessibilityNodeInfo( View host, AccessibilityNodeInfoCompat info) { super.onInitializeAccessibilityNodeInfo(host, info); - setRole(info, role, view.getContext()); + String accessibilityHint = (String) view.getTag(R.id.accessibility_hint); + AccessibilityRole accessibilityRole = getAccessibilityRole((String) view.getTag(R.id.accessibility_role)); + setRole(info, accessibilityRole, view.getContext()); + if (!(accessibilityHint == null)) { + String contentDescription=(String)info.getContentDescription(); + if (contentDescription != null) { + contentDescription = contentDescription + ", " + accessibilityHint; + info.setContentDescription(contentDescription); + } else { + info.setContentDescription(accessibilityHint); + } + } } }); } @@ -89,7 +102,7 @@ public void onInitializeAccessibilityNodeInfo( * Strings for setting the Role Description in english */ - //TODO: Eventually support fot other languages on talkback + //TODO: Eventually support for other languages on talkback public static void setRole(AccessibilityNodeInfoCompat nodeInfo, final AccessibilityRole role, final Context context) { nodeInfo.setClassName(role.getValue()); @@ -118,16 +131,10 @@ public static void setRole(AccessibilityNodeInfoCompat nodeInfo, final Accessibi /** * Method for setting accessibilityRole on view properties. */ - public static void updateAccessibilityRole(View view, String role) { + public static AccessibilityRole getAccessibilityRole(String role) { if (role == null) { - view.setAccessibilityDelegate(null); - } - try { - setRole(view, AccessibilityRole.valueOf(role.toUpperCase())); - } catch (NullPointerException e) { - view.setAccessibilityDelegate(null); - } catch (IllegalArgumentException e) { - view.setAccessibilityDelegate(null); + return AccessibilityRole.NONE; } + return AccessibilityRole.valueOf(role.toUpperCase()); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java index e2c57825fd4485..67f7932c8a5f89 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java @@ -28,6 +28,7 @@ public abstract class BaseViewManager + + + + + + + diff --git a/ReactAndroid/src/test/java/com/facebook/react/uimanager/BUCK b/ReactAndroid/src/test/java/com/facebook/react/uimanager/BUCK index 608ba5605db235..c51368c734b266 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/uimanager/BUCK +++ b/ReactAndroid/src/test/java/com/facebook/react/uimanager/BUCK @@ -16,6 +16,7 @@ rn_robolectric_test( deps = [ YOGA_TARGET, react_native_dep("libraries/fbcore/src/test/java/com/facebook/powermock:powermock"), + react_native_dep("third-party/android/support/v4:lib-support-v4"), react_native_dep("third-party/java/fest:fest"), react_native_dep("third-party/java/jsr-305:jsr-305"), react_native_dep("third-party/java/junit:junit"), From 39644d0abb45520c8f85c56ffc7135aef79702a5 Mon Sep 17 00:00:00 2001 From: Ziqi Chen Date: Wed, 8 Aug 2018 01:20:43 -0700 Subject: [PATCH 012/273] changed documentation for accessibilityHint Summary: Changed documentation for accessibility Hint so that its no longer only available on iOS Also added full description of documentation for accessibility Role as it was missing earlier Reviewed By: PeteTheHeat Differential Revision: D9072572 fbshipit-source-id: c8d20f30df588717d9ec37721c2aa3c86a0664c6 --- Libraries/Components/View/ViewPropTypes.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Libraries/Components/View/ViewPropTypes.js b/Libraries/Components/View/ViewPropTypes.js index fb8b27a36afc64..238017cf187121 100644 --- a/Libraries/Components/View/ViewPropTypes.js +++ b/Libraries/Components/View/ViewPropTypes.js @@ -134,7 +134,6 @@ module.exports = { * an action on the accessibility element when that result is not obvious from the * accessibility label. * - * @platform ios * * See http://facebook.github.io/react-native/docs/view.html#accessibilityHint */ @@ -165,7 +164,7 @@ module.exports = { accessibilityComponentType: PropTypes.oneOf(AccessibilityComponentTypes), /** - * Indicates to accessibility services to treat UI component like a + * Indicates to accessibility services to treat UI component like a specific role. */ accessibilityRole: PropTypes.oneOf(AccessibilityRoles), From 860d2d2012ca9f7d1c6af53435e4b2af74478165 Mon Sep 17 00:00:00 2001 From: Ziqi Chen Date: Wed, 8 Aug 2018 01:20:44 -0700 Subject: [PATCH 013/273] Added 5 examples of new Accessibility API to RN Tester on Android Summary: I added three examples to the RN Tester in order to test the new accessibility props I've added to the accessibility API. These examples test the following properties on views and touchables: * AccessibilityRole * AccessibilityStates * AccessibilityHint Reviewed By: PeteTheHeat Differential Revision: D9167874 fbshipit-source-id: 4971b9ae43ad4f35c6be7e8548cc31393c3f0a33 --- .../js/AccessibilityAndroidExample.android.js | 64 ++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/RNTester/js/AccessibilityAndroidExample.android.js b/RNTester/js/AccessibilityAndroidExample.android.js index 23e0fa40c2c2dd..cc52876963c13b 100644 --- a/RNTester/js/AccessibilityAndroidExample.android.js +++ b/RNTester/js/AccessibilityAndroidExample.android.js @@ -114,7 +114,7 @@ class AccessibilityAndroidExample extends React.Component { - + ToastAndroid.show('Toasts work by default', ToastAndroid.SHORT) @@ -127,6 +127,68 @@ class AccessibilityAndroidExample extends React.Component { + + + ToastAndroid.show('Toasts work by default', ToastAndroid.SHORT) + } + accessibilityRole="button" + accessibilityStates={['disabled']} + disabled={true}> + + I am disabled + Clicking me will not trigger any action. + + + + + + + ToastAndroid.show('Toasts work by default', ToastAndroid.SHORT) + } + accessibilityRole="button" + accessibilityHint="Triggers + Toasts"> + + Click Me! + + + + + + + Accessible view with hint, role, and state + + Talkback will say: accessibility hint button, selected{' '} + + + + + + + Accessible view with label, hint, role, and state + + Talkback will say: accessibility label, hint button, selected{' '} + + + + + + + This accessible view has no label, so the text is read. + + + From 2ecb2edcef8de8f7777b62d14852e3d8803c86a3 Mon Sep 17 00:00:00 2001 From: Miguel Jimenez Esun Date: Wed, 8 Aug 2018 03:34:27 -0700 Subject: [PATCH 014/273] Fix "http" monkeypatch Summary: Some time ago I had to add a monkeypatch to the `http` library to enforce IPv6, due to the lack of support in Node for that. In version 2.2.0 of `node-fecth`, this has been fixed, and `family: 6` can be enforced via `agent`, which is what this diff does. I also simplified `Promise` handling at the `test-console-call` level by removing an un-needed `.then()` nesting. Reviewed By: rafeca Differential Revision: D9200515 fbshipit-source-id: fe06acddd8e3539f590f88eef3468b02c4242afc --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 45bfb4886043f7..b429a6af95cb92 100644 --- a/package.json +++ b/package.json @@ -177,7 +177,7 @@ "minimist": "^1.2.0", "mkdirp": "^0.5.1", "morgan": "^1.9.0", - "node-fetch": "^1.3.3", + "node-fetch": "^2.2.0", "node-notifier": "^5.2.1", "npmlog": "^2.0.4", "opn": "^3.0.2", From 2c0d7b461e6c65e2b01c1cc2a8d6f319f8661e79 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Wed, 8 Aug 2018 10:39:16 -0700 Subject: [PATCH 015/273] Replace '@flow strict(-local)' with '@flow' in .android.js files Summary: Flow doesn't check .android.js files yet anyway. I'm going to be adding suppressions in a followup diff. It would be nice to not have >1k suppressions saying that we can't do certain things in `flow strict` when we don't even typecheck with regular `flow` just yet I ran these commands to produce this diff: `find . -name '*.android.js' -exec sed -i 's/flow strict-local/flow/g' {} +` `find . -name '*.android.js' -exec sed -i 's/flow strict/flow/g' {} +` Followed https://unix.stackexchange.com/questions/112023/how-can-i-replace-a-string-in-a-files to do it. The controller you requested could not be found. Reviewed By: TheSavior Differential Revision: D9143783 fbshipit-source-id: e9af4fe695ebdba4db4083de1697cc248d48eb0d --- .../Components/AccessibilityInfo/AccessibilityInfo.android.js | 2 +- Libraries/Components/CheckBox/CheckBox.android.js | 2 +- .../Components/DatePickerAndroid/DatePickerAndroid.android.js | 2 +- Libraries/Components/MaskedView/MaskedViewIOS.android.js | 2 +- Libraries/Components/Picker/PickerAndroid.android.js | 2 +- .../Components/ProgressBarAndroid/ProgressBarAndroid.android.js | 2 +- Libraries/Components/SafeAreaView/SafeAreaView.android.js | 2 +- Libraries/Components/StatusBar/StatusBarIOS.android.js | 2 +- Libraries/Components/TabBarIOS/TabBarIOS.android.js | 2 +- .../Components/TimePickerAndroid/TimePickerAndroid.android.js | 2 +- Libraries/Components/ToastAndroid/ToastAndroid.android.js | 2 +- Libraries/Components/ViewPager/ViewPagerAndroid.android.js | 2 +- Libraries/Image/Image.android.js | 2 +- Libraries/Network/RCTNetworking.android.js | 2 +- Libraries/Sample/Sample.android.js | 2 +- Libraries/Settings/Settings.android.js | 2 +- Libraries/Utilities/HMRLoadingView.android.js | 2 +- Libraries/Utilities/Platform.android.js | 2 +- Libraries/Utilities/PlatformOS.android.js | 2 +- RNTester/js/PermissionsExampleAndroid.android.js | 2 +- RNTester/js/ProgressBarAndroidExample.android.js | 2 +- RNTester/js/RNTesterApp.android.js | 2 +- RNTester/js/RNTesterList.android.js | 2 +- RNTester/js/TextExample.android.js | 2 +- RNTester/js/TextInputExample.android.js | 2 +- RNTester/js/ToastAndroidExample.android.js | 2 +- RNTester/js/ToolbarAndroidExample.android.js | 2 +- 27 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js index 420d0380a2dd8f..09547ea06367b2 100644 --- a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js +++ b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/Libraries/Components/CheckBox/CheckBox.android.js b/Libraries/Components/CheckBox/CheckBox.android.js index e022013484c18b..0c7f13decd8c13 100644 --- a/Libraries/Components/CheckBox/CheckBox.android.js +++ b/Libraries/Components/CheckBox/CheckBox.android.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow strict + * @flow * @format */ 'use strict'; diff --git a/Libraries/Components/DatePickerAndroid/DatePickerAndroid.android.js b/Libraries/Components/DatePickerAndroid/DatePickerAndroid.android.js index c8f7fb84304ef9..bd91263a8f9b49 100644 --- a/Libraries/Components/DatePickerAndroid/DatePickerAndroid.android.js +++ b/Libraries/Components/DatePickerAndroid/DatePickerAndroid.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/Libraries/Components/MaskedView/MaskedViewIOS.android.js b/Libraries/Components/MaskedView/MaskedViewIOS.android.js index 1e779382f6763f..49d44e1541dcd5 100644 --- a/Libraries/Components/MaskedView/MaskedViewIOS.android.js +++ b/Libraries/Components/MaskedView/MaskedViewIOS.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/Libraries/Components/Picker/PickerAndroid.android.js b/Libraries/Components/Picker/PickerAndroid.android.js index 135301eff38893..1f80aa3928d05c 100644 --- a/Libraries/Components/Picker/PickerAndroid.android.js +++ b/Libraries/Components/Picker/PickerAndroid.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js b/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js index 856f7116b59e0a..f343e2e5452044 100644 --- a/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js +++ b/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow strict + * @flow * @format */ diff --git a/Libraries/Components/SafeAreaView/SafeAreaView.android.js b/Libraries/Components/SafeAreaView/SafeAreaView.android.js index f730bc6ab41345..a581258a57832f 100644 --- a/Libraries/Components/SafeAreaView/SafeAreaView.android.js +++ b/Libraries/Components/SafeAreaView/SafeAreaView.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/Libraries/Components/StatusBar/StatusBarIOS.android.js b/Libraries/Components/StatusBar/StatusBarIOS.android.js index fc8b4b70dc70d0..96f77d7868fbff 100644 --- a/Libraries/Components/StatusBar/StatusBarIOS.android.js +++ b/Libraries/Components/StatusBar/StatusBarIOS.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/Libraries/Components/TabBarIOS/TabBarIOS.android.js b/Libraries/Components/TabBarIOS/TabBarIOS.android.js index 06dfe10dbc2b7f..e8e376f8a9eb7e 100644 --- a/Libraries/Components/TabBarIOS/TabBarIOS.android.js +++ b/Libraries/Components/TabBarIOS/TabBarIOS.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/Libraries/Components/TimePickerAndroid/TimePickerAndroid.android.js b/Libraries/Components/TimePickerAndroid/TimePickerAndroid.android.js index 139ffa161181b8..6cdd964cc8cea2 100644 --- a/Libraries/Components/TimePickerAndroid/TimePickerAndroid.android.js +++ b/Libraries/Components/TimePickerAndroid/TimePickerAndroid.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/Libraries/Components/ToastAndroid/ToastAndroid.android.js b/Libraries/Components/ToastAndroid/ToastAndroid.android.js index a259c17a06ce76..c661adf503565d 100644 --- a/Libraries/Components/ToastAndroid/ToastAndroid.android.js +++ b/Libraries/Components/ToastAndroid/ToastAndroid.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/Libraries/Components/ViewPager/ViewPagerAndroid.android.js b/Libraries/Components/ViewPager/ViewPagerAndroid.android.js index a3ca76742aab5a..2ccdd31b56365d 100644 --- a/Libraries/Components/ViewPager/ViewPagerAndroid.android.js +++ b/Libraries/Components/ViewPager/ViewPagerAndroid.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index 3869986e5f5872..c8cedddabb2a37 100644 --- a/Libraries/Image/Image.android.js +++ b/Libraries/Image/Image.android.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow strict + * @flow * @format */ diff --git a/Libraries/Network/RCTNetworking.android.js b/Libraries/Network/RCTNetworking.android.js index 13e9ded6d0061f..85db7ed6f46550 100644 --- a/Libraries/Network/RCTNetworking.android.js +++ b/Libraries/Network/RCTNetworking.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/Libraries/Sample/Sample.android.js b/Libraries/Sample/Sample.android.js index e67090974fe3e8..2755a884bb3195 100644 --- a/Libraries/Sample/Sample.android.js +++ b/Libraries/Sample/Sample.android.js @@ -7,7 +7,7 @@ * Stub of Sample for Android. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/Libraries/Settings/Settings.android.js b/Libraries/Settings/Settings.android.js index 98e512ec6dcd38..1e6708a182a5d9 100644 --- a/Libraries/Settings/Settings.android.js +++ b/Libraries/Settings/Settings.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/Libraries/Utilities/HMRLoadingView.android.js b/Libraries/Utilities/HMRLoadingView.android.js index 43454739b92c48..ae17636537a2d9 100644 --- a/Libraries/Utilities/HMRLoadingView.android.js +++ b/Libraries/Utilities/HMRLoadingView.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/Libraries/Utilities/Platform.android.js b/Libraries/Utilities/Platform.android.js index d5b3d41ffd2e2c..92edba18299b3a 100644 --- a/Libraries/Utilities/Platform.android.js +++ b/Libraries/Utilities/Platform.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/Libraries/Utilities/PlatformOS.android.js b/Libraries/Utilities/PlatformOS.android.js index fae79f3577f0a4..5ddf8d81e6e753 100644 --- a/Libraries/Utilities/PlatformOS.android.js +++ b/Libraries/Utilities/PlatformOS.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/RNTester/js/PermissionsExampleAndroid.android.js b/RNTester/js/PermissionsExampleAndroid.android.js index 7a7d72cd875638..81a7ec5b1a6d23 100644 --- a/RNTester/js/PermissionsExampleAndroid.android.js +++ b/RNTester/js/PermissionsExampleAndroid.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/RNTester/js/ProgressBarAndroidExample.android.js b/RNTester/js/ProgressBarAndroidExample.android.js index 78e7545994eff4..2b3d7feeafcc88 100644 --- a/RNTester/js/ProgressBarAndroidExample.android.js +++ b/RNTester/js/ProgressBarAndroidExample.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/RNTester/js/RNTesterApp.android.js b/RNTester/js/RNTesterApp.android.js index 0c7838e2931cc8..42c43b81aa8ca1 100644 --- a/RNTester/js/RNTesterApp.android.js +++ b/RNTester/js/RNTesterApp.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/RNTester/js/RNTesterList.android.js b/RNTester/js/RNTesterList.android.js index b57f33133cf245..8e8f6b791b8f4c 100644 --- a/RNTester/js/RNTesterList.android.js +++ b/RNTester/js/RNTesterList.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/RNTester/js/TextExample.android.js b/RNTester/js/TextExample.android.js index b9afb379384942..e38a9270219349 100644 --- a/RNTester/js/TextExample.android.js +++ b/RNTester/js/TextExample.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/RNTester/js/TextInputExample.android.js b/RNTester/js/TextInputExample.android.js index 4c143207df8750..30cee2eb29aca4 100644 --- a/RNTester/js/TextInputExample.android.js +++ b/RNTester/js/TextInputExample.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/RNTester/js/ToastAndroidExample.android.js b/RNTester/js/ToastAndroidExample.android.js index ec8c5cb25ff120..80ea97715ba30b 100644 --- a/RNTester/js/ToastAndroidExample.android.js +++ b/RNTester/js/ToastAndroidExample.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; diff --git a/RNTester/js/ToolbarAndroidExample.android.js b/RNTester/js/ToolbarAndroidExample.android.js index adc44cf441a1b0..4043c054f3fbf9 100644 --- a/RNTester/js/ToolbarAndroidExample.android.js +++ b/RNTester/js/ToolbarAndroidExample.android.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict + * @flow */ 'use strict'; From 7fbfaa6f1f152cb15408451657323ae84e87a43d Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Wed, 8 Aug 2018 12:19:59 -0700 Subject: [PATCH 016/273] add RN github .flowconfig.android and platform specific fixme sites Summary: Adds a .github.flowconfig.android. Also, adds the optional _ios and _android to the sites. Reviewed By: TheSavior Differential Revision: D9189935 fbshipit-source-id: 5274701b9425525337d5c4684ce4ffee841fef52 --- .flowconfig | 4 +- .github.flowconfig.android | 103 +++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 .github.flowconfig.android diff --git a/.flowconfig b/.flowconfig index 9f76ca39858e74..875fc6de979a2d 100644 --- a/.flowconfig +++ b/.flowconfig @@ -71,8 +71,8 @@ suppress_type=$FlowFixMe suppress_type=$FlowFixMeProps suppress_type=$FlowFixMeState -suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*[react_native_oss|react_native_fb][a-z,_]*\\)?)\\) -suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*[react_native_oss|react_native_fb][a-z,_]*\\)?)\\)?:? #[0-9]+ +suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*[react_native\\(_ios\\)?_oss|react_native\\(_ios\\)?_fb][a-z,_]*\\)?)\\) +suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*[react_native\\(_ios\\)?_oss|react_native\\(_ios\\)?_fb][a-z,_]*\\)?)\\)?:? #[0-9]+ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError diff --git a/.github.flowconfig.android b/.github.flowconfig.android new file mode 100644 index 00000000000000..94e6b74c947789 --- /dev/null +++ b/.github.flowconfig.android @@ -0,0 +1,103 @@ +[ignore] +; We fork some components by platform +.*/*[.]ios.js + +; Ignore templates for 'react-native init' +.*/local-cli/templates/.* + +; Ignore the Dangerfile +/bots/dangerfile.js + +; Ignore "BUCK" generated dirs +/\.buckd/ + +; Ignore unexpected extra "@providesModule" +.*/node_modules/.*/node_modules/fbjs/.* + +; Ignore duplicate module providers +; For RN Apps installed via npm, "Libraries" folder is inside +; "node_modules/react-native" but in the source repo it is in the root +.*/Libraries/react-native/React.js + +; Ignore polyfills +.*/Libraries/polyfills/.* + +; Ignore metro +.*/node_modules/metro/.* + +; These should not be required directly +; require from fbjs/lib instead: require('fbjs/lib/invariant') +.*/node_modules/invariant/.* +.*/node_modules/warning/.* + +[include] + +[libs] +Libraries/react-native/react-native-interface.js +flow/ +flow-github/ + +[options] +emoji=true + +esproposal.optional_chaining=enable +esproposal.nullish_coalescing=enable + +module.system=haste +module.system.haste.use_name_reducers=true +# keep the following in sync with server/haste/hasteImpl.js +# get basename +module.system.haste.name_reducers='^.*/\([a-zA-Z0-9$_.-]+\.js\(\.flow\)?\)$' -> '\1' +# strip .js or .js.flow suffix +module.system.haste.name_reducers='^\(.*\)\.js\(\.flow\)?$' -> '\1' +# strip .android suffix +module.system.haste.name_reducers='^\(.*\)\.ios$' -> '\1' +module.system.haste.name_reducers='^\(.*\)\.android$' -> '\1' +module.system.haste.name_reducers='^\(.*\)\.native$' -> '\1' +module.system.haste.paths.blacklist=.*/__tests__/.* +module.system.haste.paths.blacklist=.*/__mocks__/.* +module.system.haste.paths.blacklist=/Libraries/Animated/src/polyfills/.* +module.system.haste.paths.whitelist=/Libraries/.* +module.system.haste.paths.whitelist=/RNTester/.* +module.system.haste.paths.whitelist=/IntegrationTests/.* +module.system.haste.paths.blacklist=/Libraries/Animated/src/polyfills/.* + +munge_underscores=true + +module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' + +suppress_type=$FlowIssue +suppress_type=$FlowFixMe +suppress_type=$FlowFixMeProps +suppress_type=$FlowFixMeState + +suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*[react_native\\(_android\\)?_oss|react_native\\(_android\\)?_fb][a-z,_]*\\)?)\\) +suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*[react_native\\(_android\\)?_oss|react_native\\(_android\\)?_fb][a-z,_]*\\)?)\\)?:? #[0-9]+ +suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy +suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError + +[lints] +all=warn + +# There is an ESLint rule for this +unclear-type=off + +sketchy-null=off +sketchy-null-number=warn +sketchy-null-mixed=warn + +# This is noisy for now. We *do* still want to warn on importing types +# from untyped files, which is covered by untyped-type-import +untyped-import=off + +[strict] +deprecated-type +nonstrict-import +sketchy-null +unclear-type +unsafe-getters-setters +untyped-import +untyped-type-import + +[version] +^0.77.0 From 095b8f054aadd2511373fe6211d0bb339bf90645 Mon Sep 17 00:00:00 2001 From: Dulmandakh Date: Wed, 8 Aug 2018 13:58:06 -0700 Subject: [PATCH 017/273] Bump imagepipeline-okhttp3 to 1.10.0 (#20580) Summary: This is a small missing piece from https://github.com/facebook/react-native/commit/b6f2aad9c0119d11e52978ff3fa9c6f269f04a14 and will complete fresco version bump. Pull Request resolved: https://github.com/facebook/react-native/pull/20580 Differential Revision: D9228658 Pulled By: hramos fbshipit-source-id: 9cf1509a590cedfe4c3358006cfb62533058e946 --- ReactAndroid/build.gradle | 8 ++++---- ReactAndroid/gradle.properties | 3 +++ .../third-party/android/support/v7/appcompat-orig/BUCK | 3 ++- ReactAndroid/src/test/java/com/facebook/react/views/BUCK | 1 + 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/ReactAndroid/build.gradle b/ReactAndroid/build.gradle index b05e6151391272..c98c5fb639102c 100644 --- a/ReactAndroid/build.gradle +++ b/ReactAndroid/build.gradle @@ -297,12 +297,12 @@ dependencies { compile 'javax.inject:javax.inject:1' compile 'com.android.support:appcompat-v7:26.1.0' compile 'com.facebook.fbui.textlayoutbuilder:textlayoutbuilder:1.0.0' - compile 'com.facebook.fresco:fresco:1.10.0' - compile 'com.facebook.fresco:imagepipeline-okhttp3:1.9.0' + compile "com.facebook.fresco:fresco:${FRESCO_VERSION}" + compile "com.facebook.fresco:imagepipeline-okhttp3:${FRESCO_VERSION}" compile 'com.facebook.soloader:soloader:0.5.1' compile 'com.google.code.findbugs:jsr305:3.0.2' - compile 'com.squareup.okhttp3:okhttp:3.10.0' - compile 'com.squareup.okhttp3:okhttp-urlconnection:3.10.0' + compile "com.squareup.okhttp3:okhttp:${OKHTTP_VERSION}" + compile "com.squareup.okhttp3:okhttp-urlconnection:${OKHTTP_VERSION}" compile 'com.squareup.okio:okio:1.14.0' compile 'org.webkit:android-jsc:r174650' diff --git a/ReactAndroid/gradle.properties b/ReactAndroid/gradle.properties index ad7d1056046a2b..35b82ce516f757 100644 --- a/ReactAndroid/gradle.properties +++ b/ReactAndroid/gradle.properties @@ -10,3 +10,6 @@ POWERMOCK_VERSION=1.6.2 ROBOLECTRIC_VERSION=3.0 JUNIT_VERSION=4.12 FEST_ASSERT_CORE_VERSION=2.0M10 + +FRESCO_VERSION=1.10.0 +OKHTTP_VERSION=3.10.0 diff --git a/ReactAndroid/src/main/third-party/android/support/v7/appcompat-orig/BUCK b/ReactAndroid/src/main/third-party/android/support/v7/appcompat-orig/BUCK index 1dda81db73235d..386e71b135fa90 100644 --- a/ReactAndroid/src/main/third-party/android/support/v7/appcompat-orig/BUCK +++ b/ReactAndroid/src/main/third-party/android/support/v7/appcompat-orig/BUCK @@ -1,4 +1,4 @@ -load("//ReactNative:DEFS.bzl", "rn_android_library", "rn_android_resource", "rn_prebuilt_jar") +load("//ReactNative:DEFS.bzl", "rn_android_library", "rn_android_resource", "react_native_dep", "rn_prebuilt_jar") # This is a bit messy and hopefully a temporary thing # The problem is that Gradle extracts appcompat resources into app namespace, com.facebook.react @@ -19,6 +19,7 @@ rn_android_library( ], exported_deps = [ ":classes-for-react-native", + react_native_dep("third-party/android/support-annotations:android-support-annotations"), ], ) diff --git a/ReactAndroid/src/test/java/com/facebook/react/views/BUCK b/ReactAndroid/src/test/java/com/facebook/react/views/BUCK index c50da6f542f4f8..bb9559a90b6a88 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/views/BUCK +++ b/ReactAndroid/src/test/java/com/facebook/react/views/BUCK @@ -14,6 +14,7 @@ rn_robolectric_test( react_native_dep("libraries/fresco/fresco-react-native:fresco-react-native"), react_native_dep("libraries/fresco/fresco-react-native:imagepipeline"), react_native_dep("libraries/soloader/java/com/facebook/soloader:soloader"), + react_native_dep("third-party/android/support/v4:lib-support-v4"), react_native_dep("third-party/java/fest:fest"), react_native_dep("third-party/java/jsr-305:jsr-305"), react_native_dep("third-party/java/junit:junit"), From 9db3c51d11d3d4d696126de1366160586e66552c Mon Sep 17 00:00:00 2001 From: Ram N Date: Wed, 8 Aug 2018 14:03:14 -0700 Subject: [PATCH 018/273] Explicitly make UIManagerModule use OnBatchComplete on Android Summary: Currently, we scan all native modules to see if they implement the OnBatchCompleteListerner. If they do, we add those modules to a list, and when C++ calls OnBactchComplete is called, we execute the callback on each of the modules. The only native module implementing this callback today is the UIManagerModule. With Fabric, UIManager will also not be a native module anymore. This diff removes all the work done for creating the list and assumes that UIManagerModule is the only place that is interested in OnBatchComplete call - and calls it directly. Reviewed By: achen1 Differential Revision: D9186651 fbshipit-source-id: 473586b37c2465ccd041985dcdd56132026f34f1 --- .../react/NativeModuleRegistryBuilder.java | 9 +----- .../facebook/react/bridge/ModuleHolder.java | 5 ---- .../react/bridge/NativeModuleRegistry.java | 30 +++++++------------ .../react/module/model/ReactModuleInfo.java | 8 +---- .../processing/ReactModuleSpecProcessor.java | 16 +--------- 5 files changed, 13 insertions(+), 55 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/NativeModuleRegistryBuilder.java b/ReactAndroid/src/main/java/com/facebook/react/NativeModuleRegistryBuilder.java index b8898dc10b993a..ba107f1a638dd2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/NativeModuleRegistryBuilder.java +++ b/ReactAndroid/src/main/java/com/facebook/react/NativeModuleRegistryBuilder.java @@ -122,14 +122,7 @@ private void putModuleTypeAndHolderToModuleMaps( } public NativeModuleRegistry build() { - ArrayList batchCompleteListenerModules = new ArrayList<>(); - for (Map.Entry entry : mModules.entrySet()) { - if (entry.getValue().hasOnBatchCompleteListener()) { - batchCompleteListenerModules.add(entry.getValue()); - } - } - return new NativeModuleRegistry( - mReactApplicationContext, mModules, batchCompleteListenerModules); + mReactApplicationContext, mModules); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ModuleHolder.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ModuleHolder.java index f1b67e7a81ef7e..4693775435b22f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ModuleHolder.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ModuleHolder.java @@ -41,7 +41,6 @@ public class ModuleHolder { private final boolean mCanOverrideExistingModule; private final boolean mHasConstants; private final boolean mIsCxxModule; - private final boolean mHasOnBatchCompleteListener; private @Nullable Provider mProvider; // Outside of the constructur, these should only be checked or set when synchronized on this @@ -57,7 +56,6 @@ public ModuleHolder(ReactModuleInfo moduleInfo, Provider mCanOverrideExistingModule = moduleInfo.canOverrideExistingModule(); mHasConstants = moduleInfo.hasConstants(); mProvider = provider; - mHasOnBatchCompleteListener = moduleInfo.hasOnBatchCompleteListener(); mIsCxxModule = moduleInfo.isCxxModule(); if (moduleInfo.needsEagerInit()) { mModule = create(); @@ -69,7 +67,6 @@ public ModuleHolder(NativeModule nativeModule) { mCanOverrideExistingModule = nativeModule.canOverrideExistingModule(); mHasConstants = true; mIsCxxModule = CxxModuleWrapper.class.isAssignableFrom(nativeModule.getClass()); - mHasOnBatchCompleteListener = OnBatchCompleteListener.class.isAssignableFrom(nativeModule.getClass()); mModule = nativeModule; PrinterHolder.getPrinter() .logMessage(ReactDebugOverlayTags.NATIVE_MODULE, "NativeModule init: %s", mName); @@ -121,8 +118,6 @@ public boolean getHasConstants() { public boolean isCxxModule() {return mIsCxxModule; } - public boolean hasOnBatchCompleteListener() {return mHasOnBatchCompleteListener; } - @DoNotStrip public NativeModule getModule() { NativeModule module; diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeModuleRegistry.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeModuleRegistry.java index ffd2e8ecfd63fe..f13f88fbb90915 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeModuleRegistry.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeModuleRegistry.java @@ -7,14 +7,12 @@ package com.facebook.react.bridge; +import com.facebook.infer.annotation.Assertions; +import com.facebook.systrace.Systrace; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.HashMap; - -import com.facebook.infer.annotation.Assertions; -import com.facebook.systrace.Systrace; /** * A set of Java APIs to expose to a particular JavaScript instance. @@ -23,15 +21,12 @@ public class NativeModuleRegistry { private final ReactApplicationContext mReactApplicationContext; private final Map mModules; - private final ArrayList mBatchCompleteListenerModules; public NativeModuleRegistry( ReactApplicationContext reactApplicationContext, - Map modules, - ArrayList batchCompleteListenerModules) { + Map modules) { mReactApplicationContext = reactApplicationContext; mModules = modules; - mBatchCompleteListenerModules = batchCompleteListenerModules; } /** @@ -45,10 +40,6 @@ private ReactApplicationContext getReactApplicationContext() { return mReactApplicationContext; } - private ArrayList getBatchCompleteListenerModules() { - return mBatchCompleteListenerModules; - } - /* package */ Collection getJavaModules( JSInstance jsInstance) { ArrayList javaModules = new ArrayList<>(); @@ -81,15 +72,11 @@ private ArrayList getBatchCompleteListenerModules() { "Extending native modules with non-matching application contexts."); Map newModules = newRegister.getModuleMap(); - ArrayList batchCompleteListeners = newRegister.getBatchCompleteListenerModules(); for (Map.Entry entry : newModules.entrySet()) { String key = entry.getKey(); if (!mModules.containsKey(key)) { ModuleHolder value = entry.getValue(); - if (batchCompleteListeners.contains(value)) { - mBatchCompleteListenerModules.add(value); - } mModules.put(key, value); } } @@ -129,10 +116,13 @@ private ArrayList getBatchCompleteListenerModules() { } public void onBatchComplete() { - for (ModuleHolder moduleHolder : mBatchCompleteListenerModules) { - if (moduleHolder.hasInstance()) { - ((OnBatchCompleteListener) moduleHolder.getModule()).onBatchComplete(); - } + // The only native module that uses the onBatchComplete is the UI Manager. Hence, instead of + // iterating over all the modules for find this one instance, and then calling it, we short-circuit + // the search, and simply call OnBatchComplete on the UI Manager. + // With Fabric, UIManager would no longer be a NativeModule, so this call would simply go away + ModuleHolder moduleHolder = mModules.get("com.facebook.react.uimanager.UIManagerModule"); + if (moduleHolder != null && moduleHolder.hasInstance()) { + ((OnBatchCompleteListener) moduleHolder.getModule()).onBatchComplete(); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/module/model/ReactModuleInfo.java b/ReactAndroid/src/main/java/com/facebook/react/module/model/ReactModuleInfo.java index 5cafdc44edd37f..58b416df3a4c7e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/module/model/ReactModuleInfo.java +++ b/ReactAndroid/src/main/java/com/facebook/react/module/model/ReactModuleInfo.java @@ -16,21 +16,18 @@ public class ReactModuleInfo { private final boolean mNeedsEagerInit; private final boolean mHasConstants; private final boolean mIsCxxModule; - private final boolean mHasOnBatchCompleteListener; public ReactModuleInfo( String name, boolean canOverrideExistingModule, boolean needsEagerInit, boolean hasConstants, - boolean isCxxModule, - boolean hasOnBatchCompleteListener) { + boolean isCxxModule) { mName = name; mCanOverrideExistingModule = canOverrideExistingModule; mNeedsEagerInit = needsEagerInit; mHasConstants = hasConstants; mIsCxxModule = isCxxModule; - mHasOnBatchCompleteListener = hasOnBatchCompleteListener; } public String name() { @@ -51,7 +48,4 @@ public boolean hasConstants() { public boolean isCxxModule() {return mIsCxxModule; } - public boolean hasOnBatchCompleteListener() { - return mHasOnBatchCompleteListener; - } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/module/processing/ReactModuleSpecProcessor.java b/ReactAndroid/src/main/java/com/facebook/react/module/processing/ReactModuleSpecProcessor.java index ab5dbe85e96e05..7137e3944dd240 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/module/processing/ReactModuleSpecProcessor.java +++ b/ReactAndroid/src/main/java/com/facebook/react/module/processing/ReactModuleSpecProcessor.java @@ -6,7 +6,6 @@ package com.facebook.react.module.processing; import com.facebook.react.bridge.CxxModuleWrapper; -import com.facebook.react.bridge.OnBatchCompleteListener; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Filer; import javax.annotation.processing.Messager; @@ -160,7 +159,6 @@ private CodeBlock getCodeBlockForReactModuleInfos(List nativeModules) builder.addStatement("$T map = new $T()", MAP_TYPE, INSTANTIATED_MAP_TYPE); TypeMirror cxxModuleWrapperTypeMirror = mElements.getTypeElement(CxxModuleWrapper.class.getName()).asType(); - TypeMirror onBatchCompleteListenerTypeMirror = mElements.getTypeElement(OnBatchCompleteListener.class.getName()).asType(); for (String nativeModule : nativeModules) { String keyString = nativeModule; @@ -192,17 +190,6 @@ private CodeBlock getCodeBlockForReactModuleInfos(List nativeModules) } boolean isCxxModule = mTypes.isAssignable(typeElement.asType(), cxxModuleWrapperTypeMirror); - boolean hasOnBatchCompleteListener = false; - try { - hasOnBatchCompleteListener = mTypes.isAssignable(typeElement.asType(), onBatchCompleteListenerTypeMirror); - } catch (RuntimeException e) { - // This is SUPER ugly, but we need to do this, especially for AsyncStorageModule which implements ModuleDataCleaner - // In the case of that specific class, we get the exception - // com.sun.tools.javac.code.Symbol$CompletionFailure: class file for ModuleDataCleaner not found. - // The exception is caused because the class is not loaded the first time. However, catching it and - // running it again the second time loads the class and does what the following statement originally intended - hasOnBatchCompleteListener = mTypes.isAssignable(typeElement.asType(), onBatchCompleteListenerTypeMirror); - } String valueString = new StringBuilder() .append("new ReactModuleInfo(") @@ -210,8 +197,7 @@ private CodeBlock getCodeBlockForReactModuleInfos(List nativeModules) .append(reactModule.canOverrideExistingModule()).append(", ") .append(reactModule.needsEagerInit()).append(", ") .append(hasConstants).append(", ") - .append(isCxxModule).append(", ") - .append(hasOnBatchCompleteListener) + .append(isCxxModule) .append(")") .toString(); From e2ab0b762d3c75661282fec7de85ca31dcc46f0e Mon Sep 17 00:00:00 2001 From: Yury Zholobov Date: Wed, 8 Aug 2018 14:19:49 -0700 Subject: [PATCH 019/273] add Image border*Radius tests Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/20264 Differential Revision: D9228814 Pulled By: TheSavior fbshipit-source-id: cad4c15e8070c7ab2023c20045b82f7ab3f994cf --- RNTester/js/ImageExample.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/RNTester/js/ImageExample.js b/RNTester/js/ImageExample.js index fdabeae355dd9a..0dc3b30b96572f 100644 --- a/RNTester/js/ImageExample.js +++ b/RNTester/js/ImageExample.js @@ -443,6 +443,30 @@ exports.examples = [ style={[styles.base, styles.leftMargin, {borderRadius: 19}]} source={fullImage} /> + + + ); }, From e405249ee3063ba176196dd71dba49c722bdee8c Mon Sep 17 00:00:00 2001 From: gengjiawen Date: Wed, 8 Aug 2018 14:50:31 -0700 Subject: [PATCH 020/273] fix gradle wrapper issue (#19976) Summary: Just change gradle.properties version number to change gradle version is not the right way. Because sometimes the gradlew and gradlew.bat or even the jar need to be updated too. I also add the wrapper task to `build.gradle`, so next time, we just need to change the version number and execute `gradlew wrapper`. pass all current ci. none [GENERAL] [BUGFIX] [Android] - fix gradle wrapper issue Pull Request resolved: https://github.com/facebook/react-native/pull/19976 Differential Revision: D9229655 Pulled By: hramos fbshipit-source-id: 63d1ddea6174f87778612a4e6711baac5787b0f8 --- build.gradle | 5 ++ gradle/wrapper/gradle-wrapper.jar | Bin 53324 -> 54329 bytes gradle/wrapper/gradle-wrapper.properties | 1 - gradlew | 26 ++++-- gradlew.bat | 6 -- .../templates/HelloWorld/android/build.gradle | 5 ++ .../android/gradle/wrapper/gradle-wrapper.jar | Bin 52266 -> 54329 bytes .../templates/HelloWorld/android/gradlew | 78 ++++++++++-------- .../templates/HelloWorld/android/gradlew.bat | 14 +--- 9 files changed, 74 insertions(+), 61 deletions(-) diff --git a/build.gradle b/build.gradle index 71634a0cbefc06..6128d679600d28 100644 --- a/build.gradle +++ b/build.gradle @@ -36,3 +36,8 @@ allprojects { } } } + +task wrapper(type: Wrapper) { + gradleVersion = '4.4' + distributionUrl = distributionUrl.replace("bin", "all") +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 3baa851b28c65f87dd36a6748e1a85cf360c1301..01b8bf6b1f99cad9213fc495b33ad5bbab8efd20 100644 GIT binary patch delta 38551 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

sOMMW*LPCTXBN^ zcjKryBxc@08pgp(mD*$^6zS6e_SYJE7p~q_1&f#bje*gvF?$p)!|NMaHTUf0P_TX)9qSWe#Zb=W>K}LL(=2 ziPYyhNl!)XhaQg6;MrrsKB*n1pkweoENxNoORxo>?Le;;hEFY$O=9)bV{o+r3 z7w?Lc_9vW~T4orTu`+8&06(wHs5qAsy|YUU=w8Fh{Zu!s>QD~qQSN@`p#na4>)0b#A)?IQ~X}E*La_9 z94JShK3JadckwMXo;N$6AyL{g696dRNqx|S3emm7QAuE$k$h+j{JwiZ{w&c^ z`jU}u7uXQ&6Eav{Y_c;#-qO@J14sVLDESb#2`fn7)*CQ4X9U?Sr)6!*o<=lsMg zS-{*5MURaN_)(8GkAUq8N+c?MmvrwFnm={{$sQvKIQk{0&EG|x*9Th~L$Ri`z6~N2*T#5GJOOEK#b_u=w$DJ(W1-c+pVt#C&F=!K0K<9!HcOSH z)kqqc$!)*HzhcocUA(fZXLj2f+1vWOEAYJAi=J`Dzq*lqc|C(5+OV^` zWqs=aK=sRJD)JEa?jLy;9N6_rLFxC5yox{2;SbL^^ukJ8=!osv5EcS$H-q$4cK1qJ zcI=uI819U(^J6lM56Bn@%ozgZ{Q@DuABNnH$2!|oBXtEW(lUh@6DL1)&Y2ai;SNmF zb}?OEAQISMf2g%M*C&{{MlTR2l3?%&Q43xK?6YQ_EQs*w(J-7W@T6C4Yl@5aX9xBX zLIIF!s0i#wWbvjJ2!?yPgSZlIxKJ?){*oNTcXutBB9S&Ej<@;P_k;2fZfK6i9m1{i z(57`yt{Y@i{wr|@Q7CCjqP)Z}#n4~{R48XkyutI`%-Bd ztn8STS_tr+%gx#lVZ$S8d$a;L%m`e$Fkf*~iwu>x^)2xb9X+;&m-B~*-0aiH^RY}M zE{OC^m(>3I^(ib>6jt}PSDNK5B-%I)FyWyfCc9};>V&}zic1!i3nh0Wg(M}g((n?JVGxv%g|>`K%D$24B7Xp^Ce%WB8w6977LpEE{QDZRl%3#A*#*FM6v;nl0MS z$!EcmgCw|q50{>!0)F1Jc+1Sn&dFKYxM3P#3GiP>sl%{&Bf{^lS^I=pnoc|niyxeMwVa{Vk9hwmJGv{w#qD|sNx}DDL~rTU6JDq&YM%t$}@k!{5F{K zGTKU4(U;T8|3~nN=#eiYjYhecLZOr6_M8{+_j%XqHdE;9^BM`{wwPoeRS@$&GBjHH z@i;D2V>`70=$G@6l7AyNzQ+cWPX^$N@vw(CL(}vBYl>_ndq=_*0X>xQODkvnWGXJA zzVov#BAk?v1-^vcpjiw1Bk_zgq`@{t9k@_aR*m<^R)m9yIt0N@mlzE)P0HfP}kdUMWVmAuqYJ zN*n1>nii8+RO!kQ67`E!y#!ExvCyVkS#1}aRjHc>N3%|sE$EQPx?@5s2B~5n0!_vl z(&#IGC^1I7vZ--`b;{lqy@PdH;pysA=M`Pn!`z#LapP30qMrRjg1_wIq@}5D-O&T! zeeM5z&grYz@bV6IWb25DxLlMQ2v&}d-%^4{7u`ynWSogItRK&47pCvzwz5!E3QR~SnqkTUVMnUtUD#j~B z(@hE_y*}DvZiN+Ka4_w0Jn$cm{eW-=_mdH(L3Qh$C#Yfna5JA}y`)QLTzji7Jl`i- zr+aL3=J{j!A2g{p=K$tBL$4FwsV^9p5SScS{v}L9WF;#cYUyNOXyQsj%q4G)*9&%j z9h>>&3W&ZA9fwH|$T9A1-kQzcQ?c%D*ifyj86};orSmL;A%=`I>XW~Ln+-cJS7N?y z7mN%4>g?LPD$Xfd8#~94FH)o6^Z$CN_T${!zVIjjYk2#Y%>nV@NfS^0r$Ex)*FpLK zVSTVKv;pt6r8i6!n9WKq6zx~YD;@&>j3SR;7C>f%-S#>V#zR=*AO7qe@Ah{2hkO$~ zA%D{raAn?Y`f=et5P#PJ27-jz>EBkekv~AvJM_4 zl4aQF+L1adnE>9b$hlGXNS5|R z0(hZ)ixMS5COgh1s`Zj97HkQO!?Lcht_XFzEt9kzokXY&Ygx#We1?2SMAXYA)7}Wz z@d>OwFV&W4`~L)vMU@t$bOs3}qrCk*{U`)aSF;^XIe8=g0fnZ;+m!x2EeskT^~w z$b+JMZHK0Om@YEfPSN|W__uqq_*#Wg023KW#yEa{H0JH`xfa-s;L;NWhHSQ{tB%g5BFx8R zUzKc^U~YdipIUPpo|V-HR8livmG*cU=`#O)D*GALba)4MV?$Bz?P)twjnK@x8hV@6 zoOQI&nH<~c>NLia8`EL;dbGuNKyNf3Jc067i!_Nn)8+JMo)uc%T<(~hs8WD)*)GNW z6(Iv{y3UJEVz{VTgU@ACq~gDWnll!LtlOt4QB0AQP{;P$_2cURG!D%0U-yu=q| z3RVqr6kp%83NJTw-{TVmf)69ExJ(u5o*BKnajeUE6-h!czl9TM1WC;gmwuj zs+Zs{PfN#<7*M=Qa#0 9|K~MIre9kk_bcV9Rz^`yz-c@w;k8^=E+LPOVPYtfW zkNs}gpY6=asuSF2mfGpgdJZ%9OKxpsaCvC*^LyQY*rZXv)=5WP0B+#M`PWi+Usx%F ztJS$Z1ZsComz@{>E_)fKCRtbULM9YvQI+1P-_;;L7%!bz?=-1w)i5@`z}IRcqgrB8 zlG`iAex;j*vahrFBY)r$a3O@KhayAb_2JT;ARx@$=f5I;szwl#v_P(gHzTi!i5l+q zAAC_^850RPy(SZ95))(}k-9!X{crSJwn`qBcyX#SxWMk~!f|JZ+;Tfh5} zxEYnBBcVRHJfP7c*Aec(Zi@QvaOvC#nNUA$kcj!^>+dDW!e+v82ee8YUu3>GmG44` z!%;6>@sT@l6+(%B4$USHTOy|)_`Jk6l8eP6A7~zy&J4!A3Q)u+eH?1R2&|@)>Ur;# zzob^FYM*qaoV7<@Cgg^0QbZj&5TvrkFb}~ifMp$R)pDMO^a(K%5mmGjrzG@#iQ<_8 zcUR<77FaPO)Y_<(kFC}|f9W9f8tj==3FVo_a48e$#kp@4CNU}?>9PvQ+1e3CRb+?U zScf-X-(Q120+5dyB=FUQxINSGYCp}&Sk_-6QRCbP#3;bom{6c*=Nm_xc~bdWTN0A# zz_q99K*6C|$nfeU85(*px$%nEwVESz?-!#V)8tSFC3siqldkcg6Po*SUh z4U@kXajF_T&rZ=@5oFjCrB4;C=W?w))+2_A+CLB;f1>@id|Y*(0j(UydhVqe7wsb= zy}fC!kqK{E92b`(_g56upecq2*K~j6CTN!e9&s;_16Yze&ajMo$3v%i@k5LU1zh#P zzh$#KI`A=7xcr(A%75!*80DNW*UxgX0=i^gcucw z+ZdMX(&yVI5w@4SH>~BsH6}ghMf2!7@veUS*LILhZ+7q>>c5W2yUh>&4Mg}R+46m> zKY8-p94=r)^HLE_1^IKft)YQI8JTt$g)Yc&9aH=lsjf1ks;+b@#214_Eu2NVJ=Q&j zKge%zGz8kn`~1lG12OE=D@=OKuCRpH)9IW{p5K|7xtRh&0Kh*e;vfr{+JtPINIB~e z`b7KjaFcB`7SaR3wHO&>7RH012pAYadD(0y8w3Jp;5vQ-my1jly?sFMI!)?}!D z?5~ns9$U*GVWec&)m4%~u_B-JC$!9Nm3+v)zx!`LW}A2KAR|x1;9f50ss@mgas0}@ zw(`WyqE>uDw|kXnr?$*=4JUm8vR3QLUmy zBnF_`SI+7CFq%SBRU?2Ai!MB+A8Bd&M%bQ_mf>s?>~=<_V4Cz^DLGL)p?6lCLGoB- zW*JIr%0X=l)DKb;@ki)Y~GE;e? zcj+U4WgSMYI>ir3Ve_2s;Vr(8g3;W7e*iqaE(FO1Ld-KBR1&deV6dEy@#nETby$R$ zY_B9@y_Gp$T~MV6zu3?U)$Q|o*(chr{Rs|J+Y2eDG4)tYQDa+HNY%U11TyIW6Wv-h z1Xy^u$~-aD1PGUGq6(W|U{bsNFjnZn#v(4{Cr(#XY1lE#X$k6zS)g)ew;NlEdH@yn zkCiU+!UX!t48Xogl0<_o<;T_i4cWv93S5mbQ9rLm@6Ml|H92g5IB!J_it7wpj83un zTj_eze0(nc)h|oT1xFFSO|>uh{e%SbFF-jB`gMvobE&vFv#=|+OcduIj2tKavj11u z57eNg&6OZq0z5k;euhlCiTHe+Fdg86(ZG`>Pj1#B(#}(Hy8ywop#Dl0I(H}8Um)_! zi`~*xXx;_Hg+nx}jCo7yaTl~i!_f=mw=KCWDd0+Zqsi+?78=?-+S&@oy^&tje#4XM zO5goR5w?9n&e8b>(FF{WKnH zZYF%Tvl7Uy&A81hP%dF-=oSU3hWb0?oia~pTB1ZM5Lsv9V8we%wGc@qFDL;&KBeW1 zC+UoXtT*ZY{Z|d?{eHPwlKftv13>ZrF(Hm-j$)Xh-^N?DQ+poujm+tO6-7-IM-%!< zH0kZAC1s%pJIa18aJuaVIL+~!a{zq4J%bCQ$lyb3R%u?*AakMz3F|&0zQXZbqN<$$Z72dcalS- zEBv@TsBF@Mc+qv`HIE*jfm^ySou^!}@M6iOS|1Et1dO&PUAG%WZS1Wh344YLlxv(5 z^QTciL`OJ)L1o)9vdMxgfQFTzZ4ym?6bJjxFUJhPD283#tD3?|J$xG93MLT~uFQxB z6mt#XVaDOaNC8GlFVA0E)))dSn2@%c8()meLIypvju|UW%uER=oxfd)5=`tEaPZNM zPYCzA9k=4)OL*s;6lUA%E_Bfn+m;zTDoCvI`R4C9CrY~n?jeU>fK-#BYw_+}Et1*z zeX(-GFC+vshY^56I|Jj6v0<&?`lEp1$!y)qF`2StP+x}4_%l(8fP^X%`i7PHIoUOe z4QwnlWt8vAK{<%83bin@bABf zt7>JO=NI35f&Vu^hW~%}0_0`}fOUxoF;gfAt&B3aZwXO%wCy+V64O7Te<-%x zO}tOaK^7;kJy*7D_{FTwT9zDSV60_tjgHr{Yb;{rl0&0~VW;Axi-B!-x!WHNy5CkK%-!JgY%3EnPuvyy z2226&y{s}2yqzH4U0TC>gquEFUp}sQ90WLaOP<=JQ=aSoD3FZ?P|#(6gkK1JW*L`g zw$Y$g5J!yjG_efZhE+6?AE4en?HEenPl_>pG=R*0O**85q_AfZ?;%%rMtZ?v%}cz& zjYoK_Tp+_yB4{buqo;(ZcEUb@hSqMZn(4A!*UHyuSuGdZa>cPJm1vUeh{$$JtehBK zrWbQ&5`sIH(j7SgylMtTHAQHfbe#E=`~gQ~-}DoCEq!y|zrGL=3f)eiQ__&zQaURL z`&(?}+@-a9?rVL}K@9xU7p2^vE~`n0QM(YqIJ0o9dv+)|*U^~OW+=C#njdk{IVT)e zQ?&tq%4^e=`QYnRZWAve$((T&K7a{*jxTKv( zIv;r4-Ir~x_UIThM7hmxrye5ghq?v)`l4_=pf*G)gx1K|HKE5wKhBj5d=+mk?_Yyv z?-p?r`XfvK3FqJFZ3_LFZ+$ZqzD$T^XAcT)j{@pRNR;T1vic+5hd@CAjqFh0AqmLsn7az?n_K()aD=BZNd;+yJP!)CVnEv32R#7E> z4|&+l2jPGvXM|xetny3$VITC5k=z5||C$B;Z7@{=-`tMXZ>Li7+w635O@{hOlpH@r z0Vq}5a$FKd7P!>kh6)F^ASkQr$`*90a0Q4^t3Zg0MxleMR`oe0#coVC(rs0~VtkS? z^`J*W53>P6J7zaEkrjxgsV8TzUZ*p84)4ovZ-qcA4ynNjM&LD<69)x6w$~c#2Pp_J z2s8*dfbMF%tkx{#vd3sZ^DP2cU~8Q_VEA#OgQ>@Cx1A>GwhP=b-&v{34__XtzGSXp z>7?(ByU*DlXWVT8j{jWS!OMSCfUtuwWWfc0zt!R9Js365(_oI3As)%W1kv6G)pI(x zu<9+zukS8Ojv5dCjkrez@4fVfM(DI`hF~ftA@;9yrx?$T4zWRb-P1IvWqiCeU_&`h z628VQ@}I<)I(+b`f64a3{ZCMmz{)OPF$6uofN|vyEcPK=C0#@$N?E5zB?JX9o9uqz za?aX1X_fq3t~dC-e3h1V2Ax+y61=(d$S+WN@Ni}v*YryG8Z$BI*oXVCzUklVWFqi* z(daB!4EdNtzCE~Oj$^L+N)>PLfNZ!`afXo#_?d?8n7p#WB`FD=r%Z~%N}h$8f^3;I zPLRq;K5M6mg@jVJ+Tbg;x+EuYkQx%CRyy`UZXfY8@(ur1&meKTcLdcfwPUJswz3}4 z1}5p|`tb%Q=Joi5R#c18n#nD3lA4q;j|cXPfnNyQ;-oL3wvHnlM5H1@`owybf#Ow? zUvMSm02_Y1)bSv7r!n&Qaoa}QHf;|Qu<19seNN9aAFytcPsC?YKdiOEJPur!%qshR zOr0amK(PP&ra9^J^#A@Ii)}yw0TKA$&1S}q5ODrKzSCDP=XI$2FH~x6<(S1q&KNRK?4z{31nA zi~rM9_RCH8*87g%?|_NhFaJk^pOP_9%8(XN2wPx3$Y@D0eJlkf|EZN!iZ2@5VWs)KjIk{FB75ywYsbO|O`HU4(HWY@(O>)>+bkt?RIFS!FfTa{$U|E7#w zZ>0*B3fkC3zIo0x**Hm-W3FNF*(4n_$!t~cc!(|>{@Lx!*2&$e)v-Xp66(AJ1-R9( zy3aUbavNo42V|*?$ND=KltWvtSb`c=qmZ>Qnx#oMS!LTgsRQ8kV_70A2NsC!$zVFHEWmjkBsIu@W6x1|K8Smi>yleF$6i zctf{_TZk6WwH|GAnU!pVmGsskBD5C_`StxPA+NI&FBg3l&w8&gF`SYx?V%wi-0m-7 zMldd{c6lOu@dX2J`QIM+JYK}C7|U&HGY-eS4LvZoQPB<4tVzT^D{s4eK+I)>swBsS z1$%*tBwE^}HV}h#bAd!Tz$9Nav&ECR%6H%B!eNclTIk4dr7+61niQQ)ovsAWb6k^9 zRV<27*214)C*BOF-(<^^LpHBB_TSZRK@2!Ibwif~Ql&ueb6ksdg;AquZ`nfm$g=jC z$Pl~)lW~{gAPG*mi?}2N;L-wLB0R=xo@C!3=$MD(cAh@EX>taix5*2TVqV%jcbm8x z;X)HP=}k07?oWIuhM#_qf+)*Pa%kpHdZ>md=_bW$Vy9khbFEon#IZti`30XZ_bNIn zGrEV~m-Dk%Pms0GbiIExA=D&Dxz03+C3p#pj`5xs!#c~cF3)?k#bxh1joIvFm6S1#>FIjI)1@gcNo?Amcm6OZF( zLuBYez9Y`E62*+}l!y1iu=5;Eg9og!`SV&On0ASHag{|X z2cunqUaQAs+oAw304^yRDRlw+>{zm(v}-3o=jYr`04wiHm@j#+DZK;LhCV9?sB4^Q z+lHS96kRpz?_9V=5d{N^!{E!c9!8}Ai{QJC8=~nFRZVv~Od*AFlbyfQwKbFSw1_(N zoX?*L6X|*iWEmP9+{f1Tg)S)MzOVSg!dFs}+!2rm$aSdUDvWUj zy7(iw2RcA7z-qi^4P*|^d+zD<`lG+qXy1Ddj-Qe6?oP1YlAtUifSf<32wdA6%2ms` z>{f63ViE~}Q2EHth$nLYvNDvByNPJ&xYX0&i|+Q&5QaV@kSRCRJi zf8JCZE#=d*>ZC(K!HF3b zrYV^tRjw7x5MK_2fJo%c;txKgHOrnTMf+fCz{y`sCQ-`sByOnvi>ysmBb$LA!<8~B zn}^y4rw^scvZDs-d4riAK9Hn`j`hOk_J3f-M+Fpv?yd~CPg5TM#f3pDpB5-fOR)dc zg>YsFNPmC*N&?-M$M;&q8VQ^(zg4_5Vg>ge!g~ELW(1Gi{!0lMNHUSR6u?1gNf~|Y z%L{L36$6JlB3?eY3ECV!k)$AUHXNHO%b0mU3u|>c>ju*aZsB#5>&?cWBrqIEV+{Bx-V*ER_od0-EWn=AxvNgN*n?%#f2S z?=-RlZDZ`f{VAqScZE*Cjmw-la~`b8WYmnonmZ0=Ra_0$Wzw2`bBBZ8NYs+Gvr4t@ zApA#JoQNj%WEBPdEuk3C77}s$0CF`q$E1}sPTe(UoBZD>rww;jRgbpL-htB6r#t48 z-d5_Jh10Z4-6BHb+bLh|71dk%E?-rebEvNlizLe4Jpzdd&ENL`0mGKg3am8&8ArNK z1t4|0N9ym!boh|CGhusA5%-|ywSOsOtN1S1v@0yXp?6$w3Ch@nH&GlYrwStZ~f)hg7q2drd zA%3LxxiS9v4LTy9UEI(%j&ma)NJmdw@E|-SapwuO{VR$FXmn!8gKAy&bHJ}1S#So$ z3P5y_8TXOArvZmQ0T6Ev3!9X|T)(4iQxT=Z!0UAkAeWQpmi(B|VnzwR1;S8bWPH!g zgatZIv1|lW>hV}QGl-`K2#Bl1)qk}sY294Gp3%@;e~)t^ zZ^)II$%%EcfDOkbWn=*^m&0Kf8EOaZN!7&^%9|w4iWElr(xM7g^@L#3)b{LQ2&^&5 zHN>g%JIJ0p5L8HU3c;W8qSFcr(y7GhQRy*OC(}I1d~Vl7Lj3{I4H4Zi{LwGc_zyAm9UHS*)4_wWN;%duR3O(f{zj{ZxM>% zZeOjlbw?bcyE-i<4kw-pPfLU2&=+|X&1A-y70)|@Trj419Ze-hs^U0m*yzJ(o%sJK zG+MyS)wkG*WSO`tYgg@^J?-koB(J4xbj8RsYljF4)}+>$CIH^>hoO`8;B(snehS0y>+< z1hTIMTa(=^hFm5gdPzKdy(F1wweY3Oj~CU*VZ)xSLn-}$J**@}=1Zf~f*AvS#HQ1L z8?rZ+3dj}JJd46cnG$V8GxRCtINR|&XkH~%GSM6?WOcHg->MK^IA9v0GFUMY0zHQfS&S%zb_S?dJzO0`! z0ztnQ6~SeLeH$r8YGyq_m(I`{ZzDES8BGceBr`A z@bO3&q2+m}91;%OI`M37wCZw-5r}3N!zj1Z?gmbc2&&6|^4+kQdm;whtW%V`Sa$$# zJK!su9I_oJSo!D3hfPOZE_HV}o*C4tb@a*XhZrlZ-*c-6mG ztvJo1hOHnho?cD`%OSEi-)h_ddS+hl*kkK1yT~yWK(YMPS^AIW+1H(cGeWnLSE1dq z@2Kdn8NvQ3ga<4ReAyj39%~*;jehgJ2*Z|?bxpU(-Kn{KSwq+BYoGxKr^(#g za^qQk>rhaLmCsB`oLCiGDstaYeFcJXO8MjV{Oi(KMFztHztk*6y}=cekOK>XJ)#g{C(QtxD}<~Qyn398 zHath%Yf&!kFFMC_biIMNlI0F8S%1MCEk&aq!&-Plp*pz5wiIF>32ZB3gq$`}C)pXi z)});35KFrA|Jj{E{F{b%T_CAs8q>l{XxcH1emMH+X`1Iv+wvR`ynK%#B@aEodXNq$ zqiGWx_Qz!Bk_{7tkyT-jgfP+Ih~mztqSgbK%R09tt5k)!o_+!{DwSLz2sg1*Nf9(Y z@gKtfRp(qX_m<>WfC~hmP^i4w;ioSs(*K`KLvW7~O-a5jmIO3Ae7CAB7>tUnVKr^q zQ%WQ9iE-`ZV<6<2u|K$4>~xxT96Yg#;}6hYu~37=(TIM1_kpasi03K8guHHg*-m%e zZl*sz-w&~V!sfjk!baiZsEI*Qpv;!2tTMyNjpRUKP?*pTPM5nV**V)qy*f*!nK~eje?e z7SOk^X?D?yfwA3q{LbR|RLKi%Xsl;;O(xy&Vf6xYh*gY8V%eUx7(&+Cu|L-gwyHYg zH2!2O+^k4MxAXtFCI;Xtfw3a+`JRU|qyu!06)xEHsR5p7S#ck2^#>^6*t`1DR!)K# zJaEU4Im{R)CpZsS11#`&x-*DF{uU;2dnyig{{kFGi+Xav#Prr3N&ZzFYwtJlI~YV?;KkuXr2t1jSZw0SHkOcJ>RuSNg| zyRkY6cz{~3m84TA@u)+Nl~mVI1hmTQZe$ydWS73XfnozZM!YRDANK!4_t6c;7|X8}9{KB%`$7^6pZ!&|QW zPKPJ+IG#AIEf&D(LHA?yk-Q8P>*yv`-n`+RITH?p-?%=M{=2J)PF=6_Cq7Psm{iDE zdWByJN<%BOkbE29yMvUa$cFr0=Z;(F`ooXBC&1t;?1w1MQT?2{Nds=9goG8`A2AnF zd@XN<@{pP*-zbi#`$Kz+nLcRe&R%haA4ng>r1*aShP1m>t^ID5Ig4cL%e9+@jfY?R zPU*DV)Bk2m06+Q*aG<=@m(Wz?hyo6kLUj{ebMyago(bFlC`+5XJ~ZbO=2H5)?Ugzq z2~tF1&(YHwP4{7jmiq9kNmDqOQVc6dJxKk+_X3GR>$p<~xtriKt9x)(Kiwq5$4^``qvbPcA#Jns8Hx_ZEC5W|H3cC#YaPnAqR5z?WBI$kX zLXOJZZDAnbNgetp9(D*JqpcFxs{s51xL&Cn_KBYM317zO$w&QaRVH7UfMXuXz*Z+) zZ62vfo6vy&2x9^@3hzcAJ--Y9_6`E*gUaJ*0z@kK<&g3hIn9TcvSpEGlcJ{M36$arSSD=z5SNHPBgeahOeD%(7l z{I)I5;CGijwDSae5OhXa063DFKViHnPe?X7)woausiaIcdE_+6jwT9)y#If}t|N66 z-jm-t`ZRl9+s)uIm%U zwudlzx)plX$gWHQ=VSFhGJOw2jXehorL?c#7WsOxUj+V$Jb^!_bngp8P>KHC%;TPU zosRzzW>!e5^v4vXx%t&lR>=blMS_s1t*a2XlZ*lwbczV}`#SWnF+t3LWTslNv>j$v z+yC6pzVh|V>?%B|!SEK47p*ji5Q^W~tNqt?*)a$8AK3P<5SjYd zcV+rA2*+`^``7m#kBx<4M;Qh40iybo*Y>JC3-dW@U1~x!x}hB)@3+0v4@&T7u2)3f zyYJ%&W-B_oTa$hV>V+Beeox+LZ;}+Ec@Ut5_||BAhH{7M*m&G@6ieLw4nE4I3BUd^ zV?)J5-C!sWu3ZO4$tFSrO4}?ivYBIHeP+q?NN}=-$7}~PEs2{nNWMu>6NK$d@PfMc zz8>0#k5sqLftIcQJA1mVEJFqM+F_{GU^FJ^D^MS>JYdJ@x;av?TlgAXq-e>MNaJ0hz~&j*KJ_U@@@b(&T<16r$_! z$Q-g@*bqacyX0IGznIaiC`I)z469o=yD)237Hz9mRyjz@7W-Cf1@+zy-}7!g7M>aU zMoMc9>}!>FZ@2l_GG!PkpX0aPZg_sbCO)UFg`?dPes7HyOtO&WcL~!=kK2o-hVK}|3M_E8gG`B zaG;y`^XM#tkx-$B*D{icIPgzhrIfJB(Zv~-0I`qlh;lrQErk%VT4gjkgn1Ta7_aO- zqf**=*7Upz&sW!JDJMOf{^G{IoXuJ!?lU> z(Str2GAqSewaP3kr>NKvlXj9-VbY_f5UWH~DrB=VSyrLSy{25aGR+6HvQVo;^O_!( zxJpr{hEUF(M?+Dqxio9}*rYgzFu@{=UTewM<0$H9jk<3=>^Q*oPoHEmn|lk*0K#hm zo6Zz6b@Qfq8s)cHZ@95iVb-2gX=w#{WPhAXX)v4U=CMIM18P%9853^5Y>{k_IPPQH ztdYzB_9LcDdN`^UF8jU%18aJF{W}a!RvW2Jz1YjxRlgRK8EGw_{0RBDn(0zagW67d zuT1J5$&n_lya#Z$dT_v)78GjYLfs*9;pEC}?7*;7$bgYccHqC?KD;s@&Nyk>rlht- z9699Q+;E8S*wSk$Eu=FU$yw>3+=67gN@Wvk^e$?x&-J}#Bg;i^SiOiEtzo&$x{~HA zFzLr>ZkpYp8K2T!|Ngc?FGWV5%TiidEJL>*ZWf-GlPzGqsr0@FQ^a|Q@Da7SjR^&I zZM4SmQuzA&e^pCL2ccFR*JSsu##&~n%$40+GU0&WAvG;-6obiWd0XdhIAmGUy^7Lc zD#pHQutmVeH>Bwx#jT#*;vhzC$}?G~t&q7i?abZP&*T2DA zCr|&0(pNNv|I2LIBS*m^px2g?yVriq+iz-2wqb*p?MPYFaO{k3#sx)8+m?Ucq*V1( zbfBpTzKU{Gjz+Na5MFP;#0s)p!P=uEU z%$3EzWkw6bQ;51MDtWX1+#sk`lHNRH4t$E^n5NKm9KGZ;Ya+FyEZ!-ksr3w@!o!deJAK_8}9&43_2z2VGCi^U@=8iiwj6W@?xt9&2f2ICrN zgQa%!7?Cj&y?smI7W6=>-}x{Rs+Qnwo^=FHTN8ZT!9(InItrl{AeGB`DS0 zt?$Cuu7zoJfKaCJcG@M$HU%HN{Qwi3>wpqGU#*#Gk5hE<48J`vg%A^_yt?7Pc@%`=)CM+IN_K=v2wrnQ8ID>iacmBER1 zWZXqMtfifm72t5FjgG*6VWvX`Z**n3hSqI|^Gcnp*xQk*7-Ql;Abvui7-Q;G1fGT6 z!Ldw~1_uUEpHYjtND0TaRA0ir_qEY~ zBjJ6tp?qL7;ay|YNA9pRv1Ztx@M8T>9a6|3+`jCrd=eB9YMV`q}8`nr1KME^*Kf}WF8Gz;WpoiDUYnOs) zq~#bmo)E6Vv0TqamS|nHesx73XL*-(6kDRni=X8^7()^D5{@b`0#}W-iroR4zi@;H zO6VK?M>$hrFn@WIM?}eV}NlCQy3|Ix*YLoGO48gPEJ=e|u4*z|}0nUbmE?VD6Nu@~@M50W}o z?nToZ%+ew1{wLcdjIj!1ouyBNmgx7b;sh8LYy+Q>Y?gs$AfShk);kALvGt&NyS{IG zgD(=(?0|1&IDK&B*(U6;)i@eecGmzVQ0K&A+Xil|9+k&$+B@2V`2T6^O5maD-v4+L z3Q^g^SYF9iq(Vlhlr@nN5eZpCO@uJAMuaXSvQwh$$*!!08B4N+*OFxj*+otDKQpiQ zXD;o&0sJ=tkT zV}CnUl)nJgV}nL58T3blR6FJKe$AfhSYw}^)T<$ce=mLyDO@(_9_xd!7xe7nENb02 z_y5K@yqIR;SZ}I}hGvn6Ids05p(cLk1qvm0)3~axe#|(?K6>zO=bZy*XKwF%<;qA9 zRZ={%jt)tFnH%BLS^cZv_f>0TW^&pS6`}a*dR$p{($Gzj-q^70JVhm)UVZmbVnelJ zhh?T1UnFPv>$AdH2#(%pF{~_4j8BqNmtx`<+&!m|L>dma&hZh>*rrc>4_8;57_%^p zvZ<>7{6Y^(C6q2g+$ZUb_047PwYAmp)Q&{lN8%n{@c$?`X=i-=8);uua=7oKGd(5? zkBknj6kX0MZ#jZlX!^TqY{+4y|63FCAIB3hcfG^~xnq5Q75VAxA6_uQCL#}z5>8Hy zl1!yN(XHC|cU@Cj5)Fg~#P1ygHM2*m<%{D-CUkth9*nDKdbqf#o8jQ5Uy&w!Cb$2W z`G7`F*eYr|bN*Ov!;Hhsixk(HsVgCQh8cCui&1rhGtxOOQ3DB&<&K|;{~<>&^Q<#8 z_`0FZkLMYzDG>**(06uK&trYGJ1R(#5l{g=k!F5`wrlV6TaWX`aFO^~ywNhmn!6e)co-hGFk|PSF18{NOP#QR(02rH{}WX*jA)SQx%g z&Ao@^TkSu*c@rW(1+ro)(YzS>2}1+^`zIc}v$Rw7d79P1A>Apcx%(ov=uBzwPxCJW zEemG97baTM#Xey;3HWrbIfmQ)=Tb`0sK5k^v0Xvem@G7x7#91*v#l5|nTQALy_@!v zo8)UeR-@{nM%cY`sA1XD+_hcq0XO}4M@nA4Evqa`+BMpuKDOx@98FnlOO0xR3#(}4 z(MjQj5P$isLF6*a^*y@|V?}FBpQap~lrTE}z{AxixbOj6L#QF6y=t|`kwOpMgPq1! z@y@b|j-8&~8v3EkKS*}v9=g|R1lgj>13m>u%K7OBjYiK!2A*BeA(@W$y5z>*GyPd;B|}|Fs_^-Exhc2&>HwnqB4?9gGR5pM87x5Tfe#PV@753z(GEW2Z5jnQ+I1>Dq)(3X)@6YGtOhMi(-Pdot zNAbyB#RY`hh?wbvw{=b=EEnepXNK2~S$8C#e9(oszqD?oYE7h=gmwsz_X=lP=Dik@ zRLs|16%enQjFE6D7zlWRdQgh0{hnE1ULEe^K@;2jaxJG8Z$)l;?M z3JQ|CF+cqeWtjO41pi#G+`lx>&O0$fqg~u{%>IUa#ixeUPWL`9FLtcC|KVG&1ZOSA z^k2H&lY583Kt;DJ1L!p}_2`4;R9Xh>5IrQ@NSk@rR<9S)$-{yuyuIbsXI~?W&aBZn zIKQb3KRN^o}v1Z$))%DfzFqdlF&JOCQ&u(&~n}mDXp?JakH26rU72*! zJSy+Qy(c2ZW1tR3o@Q5fmI7C!okFi$V#NAS&n{`)?km}R(lxKX{*C)27LdhLKegli z;43ad)B5s>$ykK<(b%=(2bO%6`EfFXjZbdcFvV0Wa_5!dcZiCgl*M{HSR)Gd;zk&z zDxU=DHxi|#2DC#hP<6%VCzkK=mRjl-#0z1)z1-I(um{>c%4Vr6NSwbZ>JzNl&%fZ9 zflA9FxzM)si3jH=%p2<(UF|r>W~vZ?mg=(e;%l@ozfS8gSuXpvs_Tv1*ANR0Y-QRF zjo>vt8D>rVmC%ByNOtVo!y;BnfyW99kDu3cl9m&*ei<(!c;&Ky{&W>`$)83pjJq+8 z?S!vKdcWFeNrVy?6I+rit<4f!c6&yBwJ*wKRnRt&=u&e4&-}Gcz9)T>Q%3Mp@OA$} zV>{yIrfUvzmkE#i?9@&L>K31GHzitn9>U=kB&+Oj;mwS7y;eoo{@`RIbm`}xlC2I) zFTxE~rv=`$r;MY;?zLu$snJ&D1orc$dl`@29LzWyywFR~u4Cla%^ZHFEt&6*F|Jm{ zIVn86yX(^R{aW2tA?J+Jei~ccEl~ev8OLi~`zvf}MeBL&A|VOf|AtDVyO;7D7=G$R;g!w3(pev*FppuSDzjy>elvx%|xW zaGMXqP`X!m=Fp?LQHAHkr-y2mGFry7F!O$df{=2i`L+m8dDijK&q2&S@%ZAFFBYdQ z^Npzq0$do$l$lg=5v-AWrP*_K8&s{h{Y*sRiWdu z(iFne(}~I%E2Q&&*_dwK(uoi9@wkOcxM#UO;X13zZ@;K3xwJC$ap7kPgIzI4YR%nS zgF-E4J~(P$jCa)j>W$eWSQ2`Fuq;Q@d&Vs*&SvFZK@Znw#`87L&c#R-Gt3(#icX9k zudQ!m;8zxHC;4GjmQJ<~6CI_BZR_)9ZC^bvVo(qEmr^4Zk&PH|?d$yg$W>*veR zO0BQnCklT&u2OfQt?1uvOj7LhFpN(at-seIM&7z@>+VE#?!WWV}~DhRvn1 z{7I#Kysm6~do&Kycw*`s{?E8)q4pQ6c+$|6#QDUk9SPEW_vi{@U1s=vdzSv@U<-=4 zHU#DKm-PE~%#rk;d+^!(u}ofmJ6UYuB%bORkz=&u{X>tvdZD+%Fs3y!H3bo)BGCoO zqcpcyF_oWQjvjp!i}B`oFCp&}IvO+3Ms#O?|5Cwhlu%R5nqY?1g| z8U9tMXyJY6Sntz5g|+)f|bH z(2^2w#kVa<5Og%93XgZl(tsMU^b8H=@q8dN69Rl&0?#ymu^~2BcgO<3XDUhqXS}vF z9W?`0DUA!~K*n}BO`V_4PZ@v>zy*Z;+rW2s(4gSAe2i2YpuD#nv(iF0Q%3P?hbsU^cU670k+6$OEK<3=I1wh2)C zhH`e0+zYVKAPd85d2Zn8AXEH4Y7Xoq7mTCgP2sQ<@oqD0>)DS@Uch|{=~0UWwG!A4 z{!K8r6A7T;@eX{DZyRh@ZR~SIdx-YJm@;^z6bX>Sv~L86BweD`iuM%hFGY)k;r z4j&~e-2Zsh_`TE)gso@84Ah9D;*giP*{ONt^+tN2s{%}cqcEOO0)^+)#>ql8jmb+@ z(5)sm0QX3u09fxLw{`%wI0X}0k_tFd)CQQiJ3Wa8;rJfBa2$kTV~U{sW*8PqtYohQ z#tHz(NW!o;D*#pqWES{FPC8>YS|3 z3ecGXP=d0H9L=0vt;}4K_eU@Rr7Cs~$U=zz=#=5(i$|4)wW(Wc z-l`{24vU7^(6N!wOmbCnvI2HSpcZu=rVfdZ_0Q3EtPhay#WBr-sf55Ncf)hnyiYT{ zJl$`{XX|%BQ=Znuu|d$kz(H-OcGw%^Vo}*uG}mtNP;@$Mh~dWv+5&xGCo%L7D)quT zRCrARk}E@HhMHAAfu75JT%$Ol2%XQ*{;0AQZ5T{71kWU7@~>taNXlNs z#CI(QH&ty=DeDK+DX?o-gosV2Pn5_bURnrd({@sO&!OANJtC?e4At-r&dN$9r7bp~gF?c5RozcePdewQkZpk;K(qi?P-{C939 z)6gCKN2)ca5#)lP{%@|~9_ek5f&&5lfk}SAarseBvP~m3T;sg zqC{T~O4~5D)GmN41xIV2WY_E3jm?&m@gwBF{B*lN&n;#qq0@vM!;+8~59U4&d>9(V zV#vc}z#rLf&ra*Zga5$)dv^Et54*t6=PDc!!f`TTTVXQ@Qpw2DiG&BDKJMGGC?daW z)HFcK=@Pm?=ckLk$|OjlC*MtQ$~GC?qXiF_+zy$7;KZt>P;5+-ez~&u-duMYvFgDJ91msY1aC3VEx@9ybdM#hLE5*3!nC)&zi^ zS!7ljh9^VWMbF#DIurfp{lJUOWH}?BNXI>U7Be0x+1^~7bfq&10?r}~ZCLRo=s3_Q zCPKFI>5z%#mr=w*3drorUj#yE;KO;grZMH18m>!-t0eaM%^R%|lmVHE(;Zr&Y)6Ka zTD^?FkzclO__}yTHr%_;8GnSE=j|VLCEx+3}pRfyTqUP%e^IwZtqm3`V=m;+UHCS}n|_ z%xm>KZa$$+F_e$Y_(Sqo-3=;1yaLi#3{q)2E75^ThV>#I-gWHc=Dr{rl zvnHZK=9@T|5!@&!TnDFT;fo?VgK=X z53`=|x9@ksvG9q{hs2opL<>M(I#p;$*=Lp${P0m;k|H`9Tm4k!E40|Nf|YdM9l=C2>_Ox!SBM>|h(>SDAjxDoPaJ43-}Kx?gjJhBwZ6JVJV3M~X}R z+iB{s;XqndwRE8P8hxf8#BW~sFHMPe&?&?*_iLbi(LG)$Vp8(lvjj|c31Q_SXcLTRnDf0syjBo<+fmEs?LAqs%TyUM;kvmkXxoJoGRQmpK ztF!!6_)w625|9k7ePaxVnX3HXu(K=`Se7ugnPXcW9M`$Rl==YtvP*7>KezKn)b$8H zorZ0?_>< zO8r;*L@CFNslT~CC@9VUl2Yj_Uq-4w?;^F)^+T1S z^G)v_x14)aSog$1lIn(WxP_WBfLB+Xwpr7~f>KD`koCsrux_{RLzkp6ukLJPRcx0? zU{Ny>UUcxj68v{1n1Rz5Py7cfJ|L0{2(XgnCb65Hv{FI-vpA@#u7Ulh9W5F8Uw%qC zV#xmhDx7<5yErI7K-W}2K!pE*3VO0E8v@{$FX~CF07duaChaf{;?R_hD6v;K2R0&{ zRKf;g!aXD5rKv|!%r(jFT#{(5cC_?rpQ6s9dQH4Botl!=0_BFaU)yV8YisMOx{brt zO>ghp>)!S!^&7z4og>>6@ra@S+x*lg=j?CJov(rZ_vf-iq$Lpmv4DRreT*WOI2K@# z6$HWxY&AAnj$OcvUw;pV@Q^(ZPC0;LW}C#C45~Y!Qj&>%K%9qOz|*0bbpZnj%9?61 z@s$ZP|M+wbG;bt#xD4uwJr8$}#jD^gUBabu_yL?XdYz?EF!aP^O$!<)k~y z2E%awBpiw{88Zr;H7`>FsLW5FbOCfm_@u?;;uRRzy*$Bq)zKcfc&Y`=pFDwhR;zfr z1*8RIj9r#mC6p;q)*!*0eR|bCvr_p64&^_(H0Q5NNyr4u9ltEuLfwb^c=)t)@~ z?~%^WE~$ch{&G-zCl1{f=e#|oDUqVgfnAWdPZ>*! zqzd(*+CeF>&%`;?*IJ;6(#JZeez*SU(ca^y$egxPULe|M8@?x?r-2#+MR$w8`{M^t32X zG|XDWRd8K%C4Y7tsko3j-`y22D%->#kp^(?p+t|oFfQA+N6NunI2|t4>gc&mmLS>1 zL!ETm|6>0=H(0bBv!_U!%Ibk-GZUeN0fRO9o13p}yJ@vU$&&XFBmwYL%W6{A8g-Gh z6u)?N%*NHZVWyMO^YYLz$lACWgGED5elsr@pziBCvT-f z2fd4cFCJo)k+**KDvl6D6a%wjMA5&cZY(A zYU0f@-lh8G3da|v6sG2TQyB*@FG+`4xNrF)PE^Ucz6vMKoWj_Rhu}SI4st2$tZvAwyllJWEsui_ z?6;dqxgb8H#|6mQrq=47PUORjdC?QMv{3eKZgFjCp;(1*suIOx7zp#8kiJ0LUIw4^ zq()-4^^9ln?v70`3%Nl8j0B>pF7F&BR99&zke(8mx5c+)a~O{>CRh|vS+en%bfrpT z7V9x4l|@UHQNUF&uPejxtuCzf-n*z{D&OI88LO8I!H>47!XmAy@ zv zdyA+b(jrwkV)A*&4oHJqA1KdbJoqn<7c1~ZQYtl(6l$iuS7q(lOg732TFYB(aZqC@ zbX>Kx5CQDOVI|8U(WQ(^Qf1dSppQq>1eZa^(4Y%>O}lLO!@`sTXx&R8M=rW1RO?6| z;xp3EW`0K7STZ&V$=GJ1NvODqv%tulSj1N@e?nVlmvGokO%y}wsI;0n!<|iN(b$@# zbUT@o-=id46hvH&Dff2MlY=v=Wb|B;yH(-W3;}fUvE&M(v=|F^(Q`TthQKP#SMX_@ zw_`a`kKP!P&5BuKA~onRG;g!a!&7db(`%eq!qFiMQ;jH7wSmkn==nKoQZ6!KYsiIa zZ0OqCVdxC0qZoNZM~$beJ$s`fx@pkqXeRC+_ARE8bOg<9O&zQ9XYfa>&pp+FgLJu`=*>CFa9RI>4LcZc9w`Z)>xo3-Lbum~mCdsiOI+mTY^)3-3QQ zL)~h9fexx4UXTOilQymU<)P8vPqi#M%q-Q~Eq|W_>P8c533&iS@pw8D?-P9^n zP=A`Hd_LI0+;2m29Kn&ig$}pX`hxq59swF3@~LkRdK2`wX2C-q)n9BsT~lxO{;78- z4w5eUQ*Y782o+z1->^7?3rDe)8D`?KwnOG!*S;4{y6El>a}cT90s#dHh7Z1vlgTMxR=W5X6CM{#WR^k0Dhk*=jtEXz5qek z*MzD4qi{9V=lZ6dm*{Yfza#x|tSr58_ zGn?H=PIPTQY}#Fl9^3}C(n0lHd_eeC)=F(wW{4AV5eY6z8d+9efaOI9M9jwZ(sXN_ zC~wt8R;nb~sJ=X$8eNoC=V)12QV&16dn~)P z;E4oyY<#6}1cAmobZS28IKip^^_oa#GkxO1C#hc*ub_a+2b4hRwJLtDy zHJPs_O5~POD6YzaS+)C^s(+#Za;1LSX{r(W z6uLKc|CEoSN`wGun*Ovb4nV)5@(VPR{qxv{z3lOiCpB`L2%i@+c%zO(1g5vLW7%Y< zrZKX-#7HI{JA}`32H9f95bmG>w=p{h5fbHtsT=G`?v%jqb+n(vDS^}ciZ2y^P!m3R zvWmxS*!=!c0ST;2?VpNgqQAn2?P@=z1;-j+@?%TIQ>>`~ID#h!FaQsW1h>g|!yh|u zd+9kmWPu(UdoP7jfkg?Jzv?IZ4=>dH^B%xJg6DF0%t@F7&= z&9I1iZ=o@3fY;`9C}20g;}OfgRYiTSm-Ol4;#fBKYI8)K{dGtY21~$vbwz|Ta=~aF zckUDh+`@N84`Oacaes{gJ?Q6`-rT7fMJH_LQBq$*+&$DU^7eXqn;`MZ+Xj27k6?Jn zvOY&`FbAtl-6UE3yv%E#VJCIpn*~29C97nbJzvg7S8Y9aTmTe9V>2$JMao)yUVg7} zC2wP${qnauFUfewAsT-Qb8_sW{VxeogYew68+F;%vSo)DBcH6 zN@EjU+ZMWks5!VoWW)0Et8+$Mkw0Cpro2f_u#x45*`@^4pzn*pbi{8khM*-_+;j3y z7hzmoCp5$wG63;OTQPW@MON)4>*V8ae(QM!jetQSj<~Lx%E{KjhUf~EL$fLzy2=0&Cnjru1mr z!uN4-pHSA8I{q{G6AeujL`6k@8K1;xd~8B9EO%P4Gnr{^5tb_4B*unwom+?5iLRJI z34lSU$d^02Pu53>Oi<>WePcbi^~9BD7kbuQaNf@q!+f?h)0Jb-_nEEc)%aw+5#mfu zg1}zb0EmPGRbD`N&@I?iTW1t#*7AY&Nj^_>{@vy&y2tC&%3O`HKi{1G3Ek_C>nDB6 zu&*3SdXC%iD|pI3OYaxmSqof(dbMZT2O#=OXn*n3a?q3;{~7HA!@wm(zMc*W{drmU zu9ua*LRNc0!NL}fdWp^9%3gqg^T%89qCAPHxu$T^vR(K(+LE{x7<>C*=!P|%zU-p~ zG^{IRju`J0YViZLEY@_vY( zt%hUan-Q59q8h&dl4w+POKiUcl+lKW?1HG~K1e*IPYhwWrh4FI+wTq`}5tW>v+Ne3)Yy(#l`QsPavV+U7~M4WFo>`v_BD7{K3Mk>~9au$Q#jG715)?GQgm?4{Y62ETY*@CG(% zhEnd6C#p~QBF9Dr#H^ytuL zG7!$63PI@4Z=M%h(KDsq%v5bo!e@4d>xJ@lw&|d-?UYo#LWujD@&$#LZ0!=limSml z4eV|6(~=3ll}=3}-HUJfF&Yu>Em2)9rN3ego2MeBFR0;%8UWT8JQu2&3B&-tb=My3O071~CDG{5?dU%vz6<;Q%++%e z?WhHQwdDUCoaM>DaK%@CCiU#Q&VKWD?~|wRxJ1bVvSdYb_*0K8R=QM12lIvUd_Ayb+Y1P_O=&E%?Kq zC=Jg>UvMCC<3J-GKt21%GQQhzj<1B+{R#|2m+MBKUXl6`<9w{q`oO5)2WbTw7i^xL zY3@r1=i&EFrm5=}66ZX&{ofm5ui;wr0H}(nv+@O;XBC_+F~GUkaF~0Zu6ZfPoZUO} zM!ve|1ya|w)6!>UZ)XwXio#(JB;~%(f(s*#cPM*&@xVM&7DS62q_t?U6?`bGLn`@# zj=Sc`WT;oxd~kwtLub!WT(~uFj9Z>sGj$_$j=ueHweuSBflWY9Q=p;FBks;kqUPXA zsE9Dy;%y*Apd=V^EqSc7u3-=zN5kEhe|9tQ4wUWS9A7 zpQWf}rh&`{8TS{<@LUYFTpZmAAoS^=_*zeC_JeY=vrl*lFbf1K(n69cSOeA>L8g4| z>usNH^sq%RRF?f~dbV5>k^J>MUvL|-5y6Ge3rKy0v9D#qe#gHG^Y_C&lKUf%VdGmOw*RZuwwA^&vF5 zsWJQA(A=E;d2u)F;d0M4_xo~=*MptlZm!#T2fBvQB`=$4Bli_LM#zhn_h}=VTkz2y ze|J!<;+JDh)7j!*(Eldwb_Zl5NB-%6snGwAv;)Qi=xnPa@(neCS0NABGJ!dQpk|NC zt4QM%utJA6U?v%+ahF6lFo=t$RnVfGr_oz|;{4f4?_*~OtM`@L|77^H0$6mfGY#f= zTt)E6%;a&Io9Q+A{+M@Q0PYDSFnf2>5N9wa?O`xd7pFNj-5KtQ0jGU5k_v-l!kX4R z9RBtO@E#Qjn z+v#Q{6}pgTW9F>5vt92i)U$|NRv6I8RU3^&tkrja^f&x;b{e>HtL$nGfD(l z?(FDu+eZ}|S^|cD_)N?+lyxC=z11%6=oh%b5e@kKJ==rxa6I~Oym%NsikHj~2Tb3n zhwAkcP&L=^8uN9HA&9xfOimsQb{XDE!aH3Wtn&aQ(LquKMhg%)C!#SNt+0&(O9Z?j*XD0Bzlff96?E4bvN3wr4}Aknav%= zM}4idH8dv&%`Py*owbdRv zEGI+$LLT30))=4t=^<3nL+iwVz9@F(;F4sht~}j&93x8IRT)y^-l9hc-MpV>@?BM` zViv5`vT#BCZR^rkB%~cCI_4@uO_F#vs64T{3t!On^S^5dKTm=Obg^TAtCr{`+J$R8 z?y&nHbhq>3#WN_L1%=`xY(t>>W!ZQXqNbzpzvMiTr?Z8LCM&f$L&=DM@QnMI)5FOl(A%tJ5=cERT{gGS~Hcf)Nn?s^~4k@wJ9y!Cag5tz3li2fOk89N0NJIY(=8cyt zZG2D8YfQAA@!R}4o)wCNbCs9w1LWiR7j$31+xl72{d7Mdw}{5iL%3`)r^B~p*jmD3boIk%iqFqlWsgr`&HB~v67_qy!weX`nc{(!n;KJ7@{JuT_9 z9MSurefOiC4}|}|>Ll0NNtgdA(+HAQx8A#Vzj2?>-!2FOFowOzkH>WWJ4gdM!IXo! z{yS)*SnvRd!UKD)&hhwmaL0NA2ZSR$PYXn}4u%M6+~;FGA=P6;aISs2VINaY(qW&I z=TB45{sv#d0EDSGk)}tZOh3{9tdBj0VF}Rp3}1qTn_=c@2u7NHNHb5$fbbI@isA8Z zPtpL1(Wvo|Zxo@NIEAR(_~~mE=1*6kd?bRn_Xj}8J#J#|r|GMf06)gaCMV`V^5eHJ zkO9;|G_WsK00ZQGDo`Kww8FL>nLjMo~$On`!)_{Dfiv1-VJgnOrY`hCR+zmeNopv8fPsa)iPg7Z;iaTbz`nALr zWfTCO(zI*|IXji+l3mGCT3VC4N$@aVC^8=p_)*Yu8B=Yxy08L`=4nP=Bl2Wi;STp~z4pOYmgLe8 zbvTQWD-<34?eYw&AKr}SG8PTRlz5?ww>CgwwACrQk=MNBm6RN{=89z|G7efLn&KtS zuS}f0*`)mGrp=4F%$zI+6=C(7Nfz5R6Ti8QR5mWmOK@;>_Cp<2!;6=X@AE}7Y^Y*r z-EQPU)6Iam6v4D?%*{nKPKGx&BW{0xBB z+KPB#;@Kb)C~V}Gca!(cm}zVsizcg({EQ5O^- zXO&i(%~fto+BV0aA|&Q3q^Y*Fa0C#^6SdPu%?i>XOf*Ki+)|ZCnSUC9DqGE$ zET3#Yuw}Gfk5T#C3jVTA|A(8= zK*3vlVRQ;)LH9o3FgTHhJwPrAdcQT=O zfa2|2iILnb1nzT9p7*uKif{CZn93HdNvGbmRrXG*#v?opSI%^==lsi_vV1({Uf)&J zE~ctME`3i$Iy>M@KrW=Z?0`G{$V|kRzN(5`FQ!v5B;{kVXYMizWKWmpQ2kGaj!@oK zYKHp?__F@crc+2a4?Ggr4;wqP751mI!Wc|cAc-{oO+^f`G!P-0p zqb)D$!pr>R`!sDxqG&hULn(lM1<(XO{90;lmHga3)xW5ro3=^}?Yw>nn%qTx; zJd8@COv^@ejC&~^Pe82Lem?l^G3w7}Ef}IGUz3RMD*Ym~kG9s-_XD99N6FB#z0=YYo`eT{k_g2<_>_ZJlz@qdcCnHAPoL z)stJKz#UtXyfO+QrVCd>vEqr@LdSNau(z@DLv%}o?BI(w)1qxJFGPEsEb>REY35wi zvTMM4xoPrmNr!2_vhpr!=!yMDZoVQa4(FI8dGWVmYT&jCskw zVnb`%5GdLDfV{Y$@&;tlZgnmV!cHBvWCGGc4a02hbSl4zD_UIH=pVpZ7F&yAKKNp3 zEJLNH#vQUg)#cyZec%u`L<(QDY&nBUT{v^Ky8Y2DW{zgCwB6K=;Ng@`+{?}*YL(qY zJE(i3n7PE}nKw^Ah zkaoXo3+c?{Us0;gGZO<1Zov9kr zLLt!op+Q%N5nq}+j%gi|O~Ouk)Ae=b97gw{zOO8bu1EPF@66mJ@4;VjbYZ3Mt*_g& zCqS@;J|qr`9;A(l4t3bV_n1I@odAGeH@zYKeIiis6Ya5HI>NPkito2ugupoi$7!|W^7&SJe&a{?D+t)5(UO?nCmm*TafI3wgB3fnXkcb z7^eGdBahl?_imjaDb5)T-H7^P&uBjGd?d=o^ZLQ-kG2Ws`;v;jTtK8hUmQo=4V!eM zf+b=`cbugQ;a7ZQ=o4132XO8+VoP#$CABH4my*_W^;|hBAH~`DuU}m)})wiNzAs@YV;#v#sSxti7K`EMYT0}jW_&Y<< z5A5VKH#_~q!6qhiX=6Ebv2}FJJ}3&m;%KOhHpH*iaJ@xtUsen`jtZIEk>WqDFJ0@) zL2z$h3AYlKcMmSrEsO8>e+2#;3x{BrR5$&@!opzxz%cdyZLKjR#s+wzj-&lR%5N=O zt8qe?45xtpT1l7-h;1A|)IugqKrAp1wCl-1zqr3p-?>pbN;59sh+LLzOy=a1KSIsn zq}Ys-yGEsu_wc@(z3Aonu<&r>-lY>Z=tG#j>GAsR^}2&o;D5R=23m`brEWWi z?(ET}uUEX6MgvFI4FG6RaUPFXe|yI6^s0|uIkpqLy+3$^J18oVH%{G)dwJGJaU9OV z>=hL)0r#to!uQBM`gZH?5v6-nbs*d+-`j)VJskT(d)G&uc;*MaRcnSKRA`1Z!{93_ zk#z2aBT&C55Fk`ljE1X~FcI~WpFAe$;=h_q#m86NA0u@FQ~`rrXau7s)cE7$s=m1S ziVsq}g$F7y{I$j`d8!XszH9OGQd#q#58&ViDftFT;R=((3^L;Xurb=?d9}Z<+~9gC zoyX(}j{golp#NgLUDX$7U+G>?ppPQ5zy1jFy-?S`;0t2%#UbV#}+b zwYU1%5#TT$2pI16?&5)eyS}=*-lRc1=Pt`%7-r(*N4{-EUVNWG4@_cb$!mG;U@I6` z4ilt|@98bBZ*8tF<{K^_65HJ0-&{-&q|XMQC86HIj+Lmj1Nn7z2?^$Fcgk3r>LzwP zwzsl@M6y^;5Q(KM#Zoj5@lWi%)hn3CjwJ_QbI*)S1l&ss6U1R1CPVxA?ns7sY;6l! ztk+5$vrci083dBKg+I!*m0m?6JyzdyqATjnb-#oNRt6)n4f7N+1(%l|Lnnu;uSiNq z1SB!aRr5*j3_0;7vc5NR>iV%xKfk3GLPu)62RiinFLvG@nYkPe!4g7uasr!loL zkWfbp0k&DOyeLmQ(9FJgMYo*8n$IKj^Ja`>Ft}bzYb~{>U0*qX`OYvolffcwM`3d-2t&~jX6k%Z9gW59d}5s z4k-SmM+($AiW8lgd*fM`g?&%S^@k1=Fv7j|0~~dKclMTX5h>ZM|TD^EaNR z;_&S~I85M30p_RXkl~#s+4@xYW+}ON_fJPy|KT0>zlL^e$s>5U@&{Wu^jpV^hZbc-1In)SYIm(!ddlfdN zkZn!zI-?F0HjvRxQem{wBzcq0424(?(MWP>u}tDAwnj-XRHed5=|)W?8CE5-D!@ex z*DcLAUor!vvJ(xrxhZ@pwvZU@>WG-K!M;*fWu%#L=Rg}fA3jIzLW7V;3=@)YVn&{9 z+;Veau{rVYDjef8C_K3glR~KM9V9-h5bJePn{10xtNBC|@sXtwm_}u3SS#aHR1DZ{ zj!vpW-4iW-Z8~~$%eO2d9J1dJpnG@tVaEZ6%t9NZuW7l&I}d z@)TSS;>BVm6He6Fe>zYz@g=KLyp2{K-_$RXb@MVwj%|@;ey0;Q8511T#fnI`qR4fn z1UpTX^aFOWn)J70bne5RQBh@wgc~As7KPVwhlnTaXIYNetgb&Ftb4-CtAID>`3FOI zbiQRb*SMyYV`c{Y)#Td9#FY%BcKQq?WpHP1M3 zEmQYJ6B=x$n(I1EzTL)0Nbu2I6R^50iQ*Gp&97348b+4N#*;>qAywq{ht0Hcx6_obs(Ftw7zug3 z%t{Ux4j#I8o9XA0gIlc%+T>bJ1Qq#-)y=s}9JvgNTpv!xY^idTw!Mi8qkhSlV=6vz z0Not92liFkpI}i#A^_$x);JAskkdr)7)?SnpXCjYDMbR?WyqD_UWNXhm`C2j?pciU zs$1Tfvi5_l5dUoW{fF1Qdf!km0SQuMW|JA~Om1;AXyW$Mqculocx~yOzJc)Om z5U8+7F=MB&qbO(}U*un1*c6Qo+0hPns4!vViW^72{wyg%1os6=91v(@QeNUcg0Jkc zMlCOx50D}2QUeBqRVYc!ykvwL1efSx{$MXbwV=uu6^TJphoH+BCQ(K&YbJ@SB~Yx= z{S@?DAq#bCZ7H|VYqCa0Yp)b+F@~Cn3>Hz*o?&Y;MW&)a$r-IGE(ip!qI7t|u>Ec& zk8Nd1yAuz%!shm-v#Tu~zElc@pp_t@ALYIlW_ew<(*T(8^)@3x6qYwYw;QwAOZ?Ig zs^tu(dBD`RyNl()C*D)y@r{4v;*yR>KO_?UAQO2cBuFdPl;nClh8T%xB^YN4$OjkA>z`Nu>^rJYjvW;3(a3*e^^W-Zf9A!0+VMZF1O_Z+5I}Lo`Z7@=|R75PwUGO zzEKn@um^y=Bo_o%>nfU{TaFQxs=``IfODTG;k7Br;Hq~dN)P;So8y#DVKmX)GjlXY zP1Y@bc(7CSb2mR$Z@m7RI68%mR>!EHQs<0y`?7&yg&eZdWe$AlyzXk=P&38b9ENyrrRFN?{mfj)R;%ILy z@I>CAc&>42WUfK$x~-+D$?xmlS~mqT2j~w$K;4Lt{mJAGmMyCG0w9?8XiO&TMx7<} zDJSd22F|g%d(>x- zZ2(A^)^1LeG?q8fy~4YK`doajn|piC`OYT%$l4YLmnQ9A85(jY_h;{RU+YcgA^xCz zQ5T(((E_Wdp6<~lioVs>{*o4e{UdCO6!{J?^d`brDlIy;U@6si{8op&b@A-BnmB+ z{hJA^X=H#ixjU3g|29kiwnX)uXa!9sTOhy@Z$ERSeCdqTV~u=O`v2=&n{!B>1rR_$ zE%3<%^waf&c34d@vff+%p>2%W(`HMFH+aAkV zUh^H-C;#*OUteeZ0r4+CtS%?b5f4#cjgdD|UP8c7L?NUJlBr1qF-9Pk2&@USr=s@< zf_{c#AEP?ef!u>G&7nA_{ zgClBu#Gge>|DbVWPu-)Kqe#lUm?Nr-Jj92V834I>%e?r#E*J%gr+%T|R0EG4hs{Q@ z`XNAmnjKBulstxt#IDl{>y4@|j;G7oe znWnm@f>Z{tunj6#GhK%KIUn&k_GJmaVnxQ@XUT=v^=xPVBBq)9j>T@PCr2w~B7CrB zIEsAyvcTlC5Ou%~wY$CIxh1;U0@a@|yJ)~J`*hcXF0+~z)J6RuN5E9aT#R~!@Na8L0m=Y@M(EREEx8f9RZKLy8(L3XIoH`+MsFEE9n%1pgK}>FFbp@_L3KQw1|^C52pz}jIJu3QWA>f8 zVg!ao4L?de29x%o)YyJ> zca$MMFkxp`@1+%hPy-h2T4UEPdERgGAP={ma24*oaY&>u_3^uVA3TC11a81j#4?g^ z$+5z_3mCyw29ki;^_dZ);Z_-gyd)0!%1hkxF4l~=qxv`nC&r+G>lfNtW+&*Jh$QK1+wtq^9xoGdTdDo~QxjNR$(wnS54!YmUJDX#3FrQl6cQ4ZX6e=U}Ab z4uU%LDtT7EcI>!(mKuIVS|e~8ZpRu8G>0bA|V{eCp`ExQK zcdi%QbH7M{w83e*1K~0JiHJQt?XpRR(^w3OfvKaEk|?_I@FL;37oye+_M842w#(@C zP}pZ&7}i*OSvr`^zq$Iw9Lcce>=T1CO7w)OXDMG=IoP9S=xzWbTlY{Fz0(7{3wfD` z>(+kqH7s6FFfX!Ax&XNChq8Q`>CAxB{?(ub^8CH;kmjw?uIG$>0{bg&gy^ZFq9G1p z5}#jW$+Xlj=i z1YPAVR){jR9fUSDQl1cJs%5T_%_S@`!D16Q52X$lL5weCsXpLhKf2APxwY5i{&qIZ>;HK8p zgJHAgjxSe6mLF{5Eh@{x8@%NV&85F+E1Ot)}!!CW+`w6v1}7Wb{H#lwBX!7oc44N|l9iy71i^GsG}V zW_B|{$#p27C@ISw;`^&{*0>+)8(SIm0E`gA5R1;#I^qr3yx}o1eY^Ah-;|1#Sa$l7 z{of#Uf9rE8q2-0CnCH=@?fX-*8~4I zVN;AR1M(j~qmoRdaj>9(fMgJWfQbIlH~7hdqY!{ljYt5h1(v^gb2keQEEhVmCS^hy zob4?!Oj64VX@dJU>mV((o}yC|&nE5ejID(^w5nZi)r);AzFLVsnofLLn=R$Sk(w&6 zcCEV37seOH%31dAHIn)a!$;iP=iaeT{+Z9&bSfYp06yUUrDA3h+5pP6xWj<0V|GmG zs0R4$Bs*3F13s>nGXP4>AA%5lN@6@8OpQMzVdg74Hm=5cj6$7tFNKD1tYZAJ41=%q zk5f@+%~yHw@)a7zcpzKk#V)!TNA=Yj)wu77si%I=ikf}*2HKk!?GAFN@C4aceW1%x zZBUWzql?KwPEvu%Q@zIn-&ecm1K-!U2L*sDOuiRJEx#wml$-IA9FHRt3Pop@8O58s zjWgjw<2|6n+0b6M*X9^?V+|jkzegVS@Hk}HlUH`9(G@!VUHOft@_FHa_+$hZi{xe^YF!(;Q;BCS4Avy~%06c@fxBTMlR% z8z`zhJ9jeN(ZNkx81Yi)oY6cD=`)msiYHi&zW~+Rl|>lQ<1s1gq|qK+jIwo0QpXl;xT6dhv7* z-E*?xJjEFyl*b~U&wSbX+sg-B@$e2M%zO={5Dhs@ZK`XFa#){)Dk-1RYXe#z>q6R` zd6T_3(mgW0MGOku1YAZu*VjGCre#T}f==KK!met~zBB$0SML;_Nz{G&#tfZKv&NX?R~l6W6r5vTs;*IIM^xmM zQ7%gbanioykBURV*aNcA)ipHo(lYc(MKBw5C6cqTN6N4vSBJb&LsgwwtfJ-a63N)J z43}oB5%%yc2YfieO!@lCtgeQcfUqprEp34OZxJwtgAyE{U{mtTHiRmhuWwhiRxkNs zZ1|Z2aBKz(&Itct^2`OsC}?a3bIusp!xIO230}b{Wj6M~!gS#!nf^YpxlXzRboi88 zM|kSn({fIUoDl!WzhjhcUu`e4cY=`g_zwI2J zsm|yQ=;3V-XwYjw8THE=05}zNw(SHw%?u^e4_Zm>WWymTCH%52 zQzgh+xoVZHOk=f>1n^y6VGuftH#8G$!kNxZw;pCpHVzt)_(F8sP$`(ukCb+4=*C7G zOxI&N5$L;Sk>U~j)xbL6V%Z#hIdJLT+71I^*W-ZTBG~Vk4bkH2sj}#X)W7rIznBEp zf=8K+;D|RO;I}5wZi(@P?)|!{YTtffa3@9fo52mk!r?p~sYdI=Ix$#Tx4XqVoG|MI zA}6LNc0#Zi@+5Ty&hm1wEm|o(QKUUj;+1ZNMBSvfl6P!b-C5M?EeB}~*y8JwQSX}9 z{+T3m*gQ$I1Td5*BF+X%UA}0u?scW+n`9aakVA52>$*^UMo{ZaB~{D^vSOW5=h`#6 z0n3HKn#s>vPN4Lo#_0iDLWqg4AdDjeTG>c2XEE+DYi$^3>#N@KnM(s*%Hjk?sr9@K zOh;eHC}xQN^afMTzVosN+fwN*fLqB2w$SB${>fO!0eGnI6g8Jw+8+p?-YJ<~`5<@S z%7Jfs&7$ITEOv*^&*ISJK0E@lpH*8hYUxp0;mA>_h}K=Px4glfvWDdXG(Vj+DkU0a zOx+fNQ|^d1L|9#gMsKJ zVk&O2OzdL+MaIv(%*V(w+?3>qfVpLMAhLub9fjQTkE;NyVjou+r`9CvJ@3);i$upF z;JZN+8ddsaU&&39jCH4jdF>{u(@EymuB1tR1Ke6Ol)EW62V6)tCtPL;uTgb~HW}LW z+ytE*UXx9ZjI9({e^(G^-@Xi@`biRHLy7y}1>(gWKo@ajn;|^c5nJz{+(w^_m)+dr zP0!wS$qIqc^KN?(IKv{gC5>Dj5Q~Nvhx;WV;O(B{DfKDvIWKGvS?PlucSTTF+Xj;g za8yO^QhkFovWb?8r*89OWLKu>5@K|6$_mp&G1eGH^DxGNN}dHZ(T3bNXfX|3PBdCb|&%iO>Z1vecN& zTlLao8J^waa>ZDLRX{yJF{1o z{y^;czl;CRY7@MS$^Unx{6Du16~=!5CsO{u9p&5s4}P+n!rlF zR6&E1nrtdYJtfM7JH!StwC)TqBg!p; zuNW$yqAk|lWQy8PSE;a9q{bC~`J{*zOr{ZHg6S8s^bn<;(`3xjqrnkqUnPc8r zl5cZGT)-hR4x>ou$QN!hb<9xIHU%1Z=nmfADmkPVKb?x~Ov0jwKIqT2QTKd~_L+%| zVD=a^(R>yeAo_F9UL!OF4G)X8P#cPiGrb4s3?`415UPCpdJfeuPr+cBeBKremVI$y zlqE3a^eHe5c5D?X=eX5TO3^o|=VORGZ!)MUhD{;fn!+}J_Z=cuGgp@nAOk1nBId>> zx#Bk`_Mo`G1j_T;qwN1E3?9WZBA}RY#nQXUt4HLNGA-!ll8*yZh*uY1F^>eFEdm0R zAHq6|cC)#`9R2}V?Nh-=`?GLf*qh0KOpAmoU=yW%``O`x29j|nB=EI`fF34Kb%<;h5#Tt&vK2gt!dqxX%f;a36I6_z`D#%}y1s-pxU2|S z@Dd?R0g=-u@!cezsNJart^I5^(&Z3VS>3Fi&^;(}0#DEt)0knAU<1V#HRB{VLw-Z0 z)d#!BRP7g=XL%H*dH%1F#{X>R&PqAv{~#9v67*Uv(-mwfw&pVJXis1%8;@y->m9V7+r_*-EOSk*YhVAy_ z$PB{{5Zc{jFVZnQmc?9MuHl?-FnLodcd|;lmEuTvv`Vla{n@Bq261wZfZpu5&6WXH zndFEEV2QU{a~oH&iJDo{-m;$`DO>r2suVnA-c<4?3vAx`8B~Egs@~I!gcrG$K*V6h zp036UcBciZMZ>-;cqs&aW&uNf zz=~96EACB)`yhBJJlq>IH$j&e`Jc!NEY!$0;B&iD+pL3&-=ciV#pbRE+NanwuaA@jNsy!zam(3hgPBjkI#eyTyMe`TWJWdj9srVy#!A z5l*P=E#p0r{zxq{kXLA_7OuHWKF-1`FcKMmDbNyUIdvuxzBQfn5$sYh7*W&a$g| z)&(@8neRnVPsXWNg)j34EMnJY?N$b~}DdUk`m} z1Aqm2wv+0>U8{4+i3?BxhA6Vw#Oje!_xJ9)R=Rk)+QkY|Scrzg{m9rWyQOg8u1t?X zjNR&f40{u@PA#(gJ^dS=WL_%69$tKrp2k)K-poH4^ZT(DqaV{>zyBuqj&FGLuiwo9 zWaq!%{V}hvoP+{I2UrA&w}#lxwf(Qq07`dvs>q!C7k%uQT~k@W#{j8mbk~EfeC?YDM5MGHRk6o3c`+fTgYZt4VQ7t$XXGUkIU-)W>laZrm62fQ!Y*&6d8aJ!L}Nq-SeOD9E2?a&ew4_xNO$~BYca@uCTZLy|H*+>q!KUhx@b@78=x(y8Zn!y6k)o4o~3* zWTOalzvz2qYBJWMRlo}{^WZj$x@&^DTxz$Dv#eJk(la?zs9fJ8jxQI?f*k zmTEVZp)Il91yuSRk&jB%ThQ!OQ)sO zgOH0y^{!WTUOGE#Inqy8!c5>VU3m*((?~Hio>}YGABpjgB0sz4f3CsPsTp$D_|UuriM??#(ng&0wB$)%xIDGgX)a>wGs8+*bs85Ak{Dt74S%29maVNMChMft$wt$UHL368p zs#Yy8aXVXV&f_mNYA-EaFRDx_FJSKof7Yf)4zT^Qwu;MR z$hQix*`0+Q7YnVUaP9f3xAoU7tdN)JQRHbk19oUy!8vH%FhpRc4J7*$dz`$wp z1?}a#Z2y8%R>0W{m$0L8RuY;CNOK04Oh`OHYb4#2`n2f&S^rb%-vL`RNGjh&*+y=C z27R{hizaW5#w%U|x0{+c7Xp!+FeiE}#$*6^`?c?PF`Kb2uA9@BSYa)cF4!{MisN5u zsXISfp}TpM!*tow@#bZaUYC|sr0Aw>Vh7J^@^<_3R0Zp1LGg)ig$1(3xyPK=CBvC= zV7?in4)m1t_K|ave&6YqgVHvt%erQ!KToq;tntY#Ct(A@xH;?<-Rt7xz>b-pl{^BP zL82MH8jqsDBlvoiyQA$f&o(<*A(*2L*s&rTNhAMmH8nD<>VBRFoxETp(NtQjQDDnX~_VwAtnY0@Mf99ieDG<6;IW=e~^`bdw$Gbuk z%#UJotgF&+8QBe0Pv3p}PH$_a1rT9q5jG67)YWulO3asWKqdLayUZ(WJBYd!5>fRl z1-%sY^?%G;?RlGD=f2%|_{-FG)W?UQ$20_*VsgKcT@i><>-!d)9iU0)8$bYx=C}fb zO@Ffo-J30-6`DPu_0OHpqN$2jK-1>jk!_1!B*mHy@&aq{hSS_(v4#fnj?(c85y6t zSK|DN$_`?+Lr|N{y&oDjuapN6O5Ddl|FX>-N=Jc<`$3+tw5*O2ASno;C?q_U)M;c2 zrMO{q?N_=6ICno!!oS~{!^K*IK-xL#9Uy5a9I#tR$++RDB$S$XH>guGh9xS5q(R6p~l|TF*a?Iu)!bB_miQ_^@bMqGEn!QSAPmWTXcDhkV2xJ2GddRH{-F)$+ z7g>I z?*N*ik+_F|UZ**%SB*^wMd)$~dZ;?NdNKrq#=5dLZe<;IPe&DoCA$zceYhyS#S6&bl08QLb8-!?<~^+Hpvaho7gXXe+)FHD zZ)lqm2ATnNg`FC|Z*!jD5#jsq|ALhMr|jcdV$@Cj^s5^`pI;n5pO*gtnVLH28(A4M zB<#3gB*exM0Bly~6uGf%m2SaB;c#t@eTm?ZGYv2>8PkaG46&!^&NSy;26Ofh_agrG zN*cUg#*k!hushaD?}>QM@SSkYw7qmT0;+vJA%6EpN3tFpJ>IJ!{#ewbNOe?(&=V-S z(&}+>`yXh!QtAh{&d_4exG1_TPS#k-d)CZk4sYHNfI1_>b2xAGfqB=ADA299O8nG9 z?9x@Xsm&FJN?p*LnLMF@@)j$7MV+!G2$iI)E1gTKdi1QFfR4U^s*?>Bn4^)e#g%=$CT>)=AX z;FRK-11QriEL3%>JfiiNBK)F=l-k%2w)^6AAHuV6d|-Z1T+ZdQ!}Q?L$_TGcbsDs2 z?n@LmAV#OvILAVF=-}p^u*v0QPaJY9G>tq&f793gW-G;Z#qb`9tCyOx5r)swl zS}4ufsyC}BLdhE$w7Ay0|CCU+X{h$_osXu30Zdjy!F1-;y3N{K4)8Oab3BGILquqi zyL7!3WoZM#@`y&s*?h;Ne%wt%jbHO;GI z0h#=TXiS2>!V0k3&DcgS$UroD| zE)T&LzIJ=si1G$_t%om1fMGIG&1Ql1#kAuwhA6f@LdAS0RPI7cZ9Z^i8$^1QoEjXE zg{4_@Z#CRH5snFWN-E4~=bI*Hvrv`9X{+HO`c~Ok|dBsNek2~z6+J951sz~pDpmA z!4hRcM0Ozb_wMjYe-ti9djnQZ!T({U{^#u=@fg#L|6!%3!6(e*5hZ-sA_5#2RFS?C zu_o%oP~Zml2#9k0>0mIeN*nN@pu@?4Y{M)Wu5hS zwoiNEOoASZ-6qNHKp&tt2LbeVZZg9g(3`dCuXoxc6Qp27oMiqyr$r{PCY(5fQ6~{EuHiyNmrs~2YiMp&RB?gu#&&xgd zWj63jbjQVbS{xArlQI**FH(f z;4LMMS?T6vwV<&|i;P9-&Jg zy;YqSlcmkSp0k-P+yUlIXP-X6+P|xnM(VNI_UX4{eo?A)vsqjgrdo|A;c%9^9E#)LW7A%>S zKseJJC?5oH$*zl+ye`Uco0=Sk^h~sbZD*973UZ+#oaSA#8UO`nwKZ&cvM9^u1GU%S zb%-biq7_N{E}$z+CTVM}EK% z=*jkdyb21t8UhrIyh?XTy(STswPP-fn|YSFu3Zy5c+kHBjzTd)4gYAaU7=piv3&a@dPbcGdnfS-J1>cT%0(lQ1p2 z!y}px<}WykLA$GY-K=vLqPEFcZE_CIy{B-;Oeyk$&N(2Y2qr9KWkt~!Yso*?klTtD z3SUKre5$ZdZ^7K0&qh&%CBnb2vM)98>TK@2KAKBag`5Nf29FrQF}A88Ssy7Ow-9z> zIk~a}$K~OnBVgy9D&F5%ub|bkpj!@UYUkx4C)4f-bbGwoQ4Z$UyNia;Fgc2Q>^-rC zj|2~iHUq#oTX>vTWMfmQQ9y|7fn}LbsIfS%fi_gC)xi!NABDgGH>h>+AuMc?Ar!7! z(0t&s0Pyu5w!I#A;D~78bzS(4);=3Sa9p3E9vpVWTg0T zQlTVW>*Hb&i%p=PU4wkA@uf4&rA_I6Y!}xf%m6-K;|@J!7vXZE4U#zm z&d{XPr|S|@&eEqV-+Wq>O0#!K@}}wR(hs0@;c$#}knaw`a}SjKh=CW)fLZL=sCg+m z_E~Kq)O<~|K0k4IIE>FbJWku3!WhH9jhFe5#km(8OB+Qk6rQ$ONWUBn)X!7oKR|Y! zA0Rs#ABz{=u0dS$tHw}xGDAnvy8%&@w1F_0h48`)Fhr)wnzc*HaL+zqcPJ(ORnO~L z0{eyzR~8lmRV3B(WV-ESn$Pw5q{em!nDv$y6jXs(@{HV%uPYH=*{Rhc*JiiO&pX&i zhKq*NAT)`V67H^Qy8@U?riQf8aSBvJf&|Hy1nn;#3MHfS+SLACVEE+BrWf8hg`i^xCHMBxuC zj(&d5F0fNt6{>$7=g#t8Sx znR0Ki{2Q$Awgj+1am?d-Gn1$7v1u}x01D2x~us2z> za4Bw`fdp@DI#Say)9^^yr#n`&u?26h=3y2m01RWqAxe~tbGgB@eOlwuJ@jZe%$qVy z0L>nc5`TlJLX(XPLC%2Vp;GRhb{2+X)9{0n=J*4fZmxZl{DfPcd{d`nD28RHXvxD6 zjEr;pZxf7%Hk_4nr#eRMVMi}*N>wfeljIMx5=pMV{FtX+#5J+oVmN;@B`(~GVlLQh z0I}CJ$ZhK*mZCQ@UYk@sD;8d5@@h~A&e}v>Py6A%k03aIj}Iu;Rv@x8-3uPs-`pD1 zPaLvZZqd0jI+sSK@}d9Dp$R>vdace=@viBG!0cg$YS&9{F%H6(bREW6i^#O4-Y>oUlgN*7qOmf21 z<;mHYk!e~Y7_Cm~ zCb!!+&;)g=e_c|zc>)cAtIvG2wlP%sLui>n7T(kb)qW+diwUxY+geu*7S&ys>v5Td zgO7rxyqzZ@?k6=GQW&2I(BQIK*LQck7lZ)uLy1GHfJZz$Xp9$%%mmR@i&Q1<(h9+y zl(*V6VTEyR7g5EM6LMs?@^W}5&m~8v1HlPUA7q}ZnhQ7V<4Plq2oCw{QKC0p#MA&U z|5)N#+}wbQY-5U!vJ+}V^mr=SI22BiFiL>l1Y}z^jy@LmkF`k^0AZM4X4$a>zq)E3 z+)lJ;7<8cc*0pI9!5rtFj+3ksSKSJhTM#@dm??sP&N*si@8f{QO3IQL?2wIA>9@S3 ze{GVUZY?x&o0Z&@w-8J3v>v>`bkOQ?Jv)+c!2QxJiGGsC^-qVb&UA zOURWuO5t923H|0We4sdaO+R9m(`FX2bs~456P3{8H~$L|5+u7@9=7EOh5bIyDHW`% zdFRHiP4|3m$Qe`deqMBd&}G~(&R^qOf^Awj0n(g`wDJ(%XS@qd4ezMo54i5+ngzF> zzMP{A_%FO208r*cG<|^WA!ukoI81=R3mQMT(d~fO=q|$o zAA~@EjD^?WZVgn66(qtqdjR1<4FxC(Y7eMzGDyrPltSaFdjyR)teF33(7u2NSxea3_|yiWphr&4ev zfLt448b97_^dtaWq@Ht2rr&OV>n+RA{JEq@0v(lox4qWME=_<0w7pjl{ogKYb>X8Eps3)RHK^j0b@^>LChcl~DloWP8o?VgyQmNy zVHxB}nbF=DveCqf;fm%jryE-9rp+);<(B1BZacl2NSd5>fthl} zOLNUVjD^;vZZo~Bxcw1C2hTmHSTn(2fIw<%O9oGcaLr^$@d>W9W&>Sm6ovI6xYACm zQzwWTE*2A-L$qHC@|bq~kUcp9;8V?BHaYDQ&R5ba4+^U?-)5Ihn!27JS3UhC6sMJn z0Dpf-Y|mkMI;kLPhEY#8Bh7XaRJ;EB6m=K!EZNq71U6nvwNMSOy%ql2#m>7>)7$v}YQVy?DJ8PkdQn3kF`Nbz3WAFv_UVl}y z`#tc8)fQNGLG(BSit8$H#POsgq_oy>cwQh}tjk@HBEIsXq^P9f>uD}4;!YSfv@~+% z`ZC8^EaLUY!>8C5F#C$55VW%(VoI=2`7gU4nveAk>F8ylkV1pIZ4YWEVsD>-`vNKI z2cihNPtC{LG<@;$Jj;r73Ebx-_WSJRkl{M7p`wf37@5ihs_J;<-|JDga20)DK5T8N zGCjAEMkt`La#zs^$k{2zeFbfg11NAj5T2=i(QXYB zE?jZNf1!NvN!HpJ4XB-2zHUn;oY{MTbVfUC0gSS`Nwj1YY()>9Ks{@_^t&OnTs{9b}Sv!gFOtobv>G z-&^hl^oZHuOC-x5{Z%C7gUooLWD-~8%ZaOEAMEn|g7#qY<91{s!LCVaBQCZAg0k9e z$CbvD2K_}3t__)`aR_H%&!E0}(rZ8%|4E(!-jUZ9Tqoy`+trxc-I=#9+O(l^MSYLf zMkp+e;cl|x20FG`KGx@gc|806NicZB0OH*U2rbL&hd{;AitCLZ@@MoT&~!Ll{4fS( z;sRf$AWB1QP6O+h6xD)fsPrRT9+<)1<(P9t{l^AvujeTyK?e94+wHwadB-r@R2E#= z%b~0tV9Rw&)9qU|5UhTkEaD`qb42YbuU!Zk1;B65NV$&_xQk%l$-OsQBd^fhf~MaC zv_2af%Q{o0!M&D2R8!c1!7n_{I)lT}x}WD9QuA}BL(YDc+N)7nE&>gpJabZa1qyYt zXTSzc!PF{BhDP>KjU5^=YJ^QLTm5SL+5}5+o|h49{6+NV%E!0()mt8GLE=fzC6EG9 zRsoCG`&_Z7rgo3B${($?R&%vm+CBUQpg#|@qSt#h^K{|u6ee?ON1+)x^(guVwF76;}znpF!OGlATh#WR&f~8gX@Ntv(~*DNpMeVgGAP>!`39WSdSWX;spLkE#2-u^u$^p@ zJz3o%wxql}CFVdKluREyfzL0CfbgZ+C#wD}88#!4M96x0a336nKj!vuv#SuT-~3$> zb!@w(!(^oi=6>5hz+9*|ZJ#tBQ2}w3*EfxKXjZ#9t8U2kZE>5+OYrwHX%?w;E;DOB zK=S;<36P4`G6SQ@gB$740bgO!FNTS*_mdQ}JV>2I1-0HZlP*uGH_JnMfObQDWlVE1 zCIu^>V(OwB1wrv9(Dc9KCt$8i&B7Cq`hQT_O%T0Bf96#m{U}Hr$qF%MYk_pvxL z1s`&#z`tRWHf+tfymLG2z}CTj+kDb~;yxcs2mrrx(g32I3q5WInn5rpP6c{NAvc3& zvd(gAP5}YS!S9Gb^%7?-0O(lj5M!ei%JB{C7*Kp(?Cnww-rrVP%@ zkZ7-k2QP);$}}BGy4Qjzz}v8JcnnLdAUgtcX74OSpCaiB06%MfK>oz3EfvX^yeFe8 zeWU{{3*R&+)2i6aL8+ARhgl+)#1d0R034Fpj1Zv4-v#s1tH|Gl10fKZrh1DLzN9Gk zQxs-hfh_kE<5kUpgmNcD_U+~eOc(S6$;WUJ$W}2`E6Iu=cqh~k9r~8(aaF$@|23b5 z`Q4}JFnvq*P53zn&}TvvVZMASS*$A6oI;8c2yl7)ji!FhFKn~IqO6L=BY$T~_1IWW z3=tk^aX8BR_*F^f9a@PIi6^GhS`%h~nZFgqqs6gKJNHY(6Mdb}?8Se?bXK?OUu(c~ zn{zwHl`~dOpo_rzOnw)^gP55>$TLJEN4w)G(E3ck7eylnet-@B>?6MIwZQ++K>mx! zKVOib>!ATq^nw}_MRf}6WOB8{U#ezv6}uyS)$t+@lg_s%@ZK)`zkMn1e^O)g! z+1%ke*>>E>>FNFi`aK*DfxduKpL#|qrN&f29OVvAfuWqJLdSe~?$a>FSF!KLKHxTl z3Ex26dbDn`^O0kxywFq=u{8*kWC`)I@bbYkQ{h-X)uW>={$}% zZrxvL(>m&p^DvTy)RK=N2Amk{MU2>jjJy=KAG; zqhXQ7GlmXm-m{Hp|Ll#cVp>09VThO{4e9jKnJ6Gk4<`>k5`Aa6X*%h7@W|X=)mLI3 zc1Gv8S09!OZZmu$8o0D?&e6Yn-4f#9bXNml7q`nl);`dXzcG28E?s=*>F-y))||Nv z72!_OUwp|Exg~XMJQEZ8(MUfIO$s-E*IrV`zvqtflTHAcBT6ZmO`cgHhTC`vS)?d~ z2RssphN~{mj-1b?27#=JZ(LLDgCR+yOq_Cs#X+@;7Cip>L&#GJcSyb&&XkBCLOcN| zi)9LKKt4dO$~~p>l6Y^+1BgqTtiGH9)nbFlSg#<|A^{gUMUw>`KD1)x-H5YU##?xa ziSLwHI0Qo*Y0xH@FB4l@J1AoC6Wm?L#YE=JMe)^cfns-u8mFGwF}I@GWF%5BVw*T| zX>*BDf}c9c)4;*St(fD?6dobY_JUL4$gt+876EeoxXgO~E35Y(A6H_|?)9Fz9e;9cR?K{7$~%6n42k-(1`8raz!cgL1v{ z725d?&tpvGb=2Np!^H~)cBN^Vz0;V^Z_C+V&eN>&phi5U2oGl~*8tr+U> zs?f$>&Wd})dnAU;=TE06TytRQHVPEHf;sQbpY!uy%*zFTRuyv$Y#7WwCb&Bf9WbH1 z_C~>5&Aa&X4;VRHj}IT6&c>tJ5l@;)nb2r`EN%y^xZ}8JIyeK}GBdXy9waRs>Q+(C z&4#?lD|fb@$_TtHQ*C(kMe6)*Vx9x_Io$A%+0EmbPry8x2@qiMm=NQ#DagP-LlC|W z>Eq$qG{(AcY%6+s9Cz=a--MXEa?PbgH!m(bo;e8S{cMH%T*i`19G23Rmrq+R9FLmK zz%4S%$mgumc)+r6@Cps&a)olq%{7Ec&VAtu1Y2MlEv1^!%e;R>fJ1GCpi*eoA5Vxf zI9#w6wdOCy0;n_fkjBXn=x3{SLUPKJxr~0c))-qn7iD|ApY3<40svTcpvyul>AcdSeUt$n<_asQC+k zv;!BAiMLuOyi&$+?^3gT}6uQXd&cVh7y4A$1ETbG$&_7J(r) zL)7vG+ItOA@^rcr?Gx{OOAfA(IKX`s7F#}}1aRQ386YJ`<&QJQ&pA1Fsg6|~dz1gA zkRmcfOT14uu<+VOfqBk0VbY$#GNIOGPBPGl!W`G+O=_`HqF&7?R#cJGQmQg8_@nqp z!qH)M3Q49s1qK*Um*P|9-Yi{D&tr)UAx-l>5)4a0??RhdFD_1zbnY+mkZ3}$s>Hx9 z_NdeVSF+T=qr-ZyRxM8h<3i(yZU$X1HqZ==K;5h1HVj@{xkzZ9b9kb;qF|oKfR%&6 zvgw%Rq=>-pK#^m%XjYA`pqa#y0T^Wn*lJr{Wju%Saew83hPOCzlx0~^)v?!v2R3><5Cm_6^H5m zD%R2F52`(jnlV4$iHd57gSSJ8h@FxB#EiY5BsOpK;ZLktMZlrAk9}(KGE< zhJk^`ii*Qu!QYgj)ffG-mm|%Ve>Vn(zF5m@XDjxVmG+5|t}B7Cr}ousTDAHabDPSk zlDewl@t4?klmCp7e=RSyU-1qgp6V}UNxdkocAw`LV=lc9{}QRiL^uB;TQvKKs`Yfu z83LHhmfwlUJ-bnzIn7XVVO^7Bnw)+Qaoxs14cqcH-OSR-^KHq!9_Ivn3WFk2ls)nE z6BYN~R2BF>v;skaFu=J(g#%dN81~wzWug4`AjC1eg?47JBIcYPp$v7c1cu0_ zI)(m%`au()q7rc2s#>1iVAh!)_Fd$53nu!nLLsBV4)%u(iiF=@A=OI+Mo83(h5|5< zifkiigY3{#%zo*?y-_5oV1G%;H`j<1(vB<`U99U#hyMv?LRA{u9EC2P*7i|yx3Pfw;f z7P}r_fBk#LSehv%-pHy19*$-tptDk6py8ES+;|B+qU$QVlubj9L`H5@bK zt``9^$%f34DcW;XtY9@8CV3`WK_l93Cf*N-CP~D{0xg}F+JsJ+)jCvU9#al<-@gV1 z%Iw@)y{h|jt=gR}*vUb8s!W#96x^1IM}Lo1*?05@k$)1Ej=Eqo$LPK%Us!b>ll-Rr z*evPnzTzxiZEQP93)DimV&2FJ`?72w+ffC`-3J0f^|8`uuI|)2^&CqSsXqE0a4OnL z;1qx1)bC}JMGZQ;XrF`{Gnkg`6M$k-45;z&?C5T_9^u2g&{?fuL%4T+?M5-U1#QqjFia?)6`d=V zq&;X(J$7F9)Uz&VRhZr?QG-SdgTnBel8hk01`$@(| zGUyIn0Q>;+hJwyg+#~olyB8r;tx^|3xx5#)$6Wn8dyi%qB%2SeQBmxGC0~?HFxgw= z5}z6Jw`&n4%cA=~zCVzXmk`y@bp>To5Y3^STIcihE>01CHef3oYzM7^%S1=iWZr+L zX_2`n@T#frX%j@Uk)Z3r_q)U}&R%W*XF+YSw^9A?$qtb@jN@}qARsT;{}Vt2c+&$` zB?AO?p@b>~kzkQyQNpYf*;iZS)EAbFR@SV_0eJ#>-~H2#0m)_0TBh$s-vt8s3y!Xa zP!zR&_Qij%C)$1nU)yG~J)ggxZfqHV3hn<6YfNV4o9K#TIpSesqhJ`*?P>zav`*iJ zrP4W8LaoAMGplkfL)1>&D-A>NCous+<)Skqk(xR0@mjFouWp_^oPzb~Of{2~hyJ)$ zXqIa)DQPsQDn)H&+L*PdR8(tV3p1Pt+b}RyDtHY1mEb(yV%IjY$PgM&@4y+r)?c+) zlumb+pjR0~8Ba5AYOm64PvwY;&z(Thox9FRZZ6hx?wF-w^Jb>P4bIb8E7t_nSb}9d zkYQh)hsxtn5ejyMF1TX^3oTHsmK&cCuC<%nc}+7OMsKM%nkCd^jctNHL9(f+L`j$H zX|*ekIcXMmmbt!CAowhmL!EK|n`>dg=M6hV*aS~MMwCdZ%c)f z@B@ZJ+>xenZ;YF4nPBI4T^h#1nhek=rHA6-UH8huwxMSZg!=1uPS}SK zyOUrK9e2Pq-+_;$z=W^rhq_6X?hC+Gi~D%gQtgw)dGfm?+KdPUjS>2kN$aZo!c?M~=Y||4+%b5-oi5g; zU2L|W$obc*TvE$#k9A9cQ%yR=UsGZ9%s&mq@pKRWPgz$257qX^$C^Qw>`X}35JUDQ z%d@4iJcKMsSrRXvo~(@#(nIL>SF+R7Ly63jkbMfzC_|4Z3Ptj$-c(ZbKX;hS9ryFO zbLW1}@B91y&hPxrxpVHF-?=`~6Gpz3hyLO_^Hg(QP z3+4hZ%x}-QQPt9bwpOWjXvT3$m%~I}H_#zGXWcX`>!ha;Po5OSDiED@Nh&!rISk2c7O6w9nW(eQY+)J0jkjbbk1D zc2v+CgZLsf=lO>U@4bD^3VcZ_^MaVf=)FO^q`P<;tr|5y7TcM|<5u-9eUm{B2@uLC zFP;U3`Ub9Y2DCrH*9W!VWgH~bMS_#IfzoF1OI(XKfjn9uE!+Ogb)S$PMpJh_URxX| zf9+~^7&?$YuGy@s>9SYkxH?o^Adi1&Ejg~MH9AlhGA$9MHmtsnE6=@%S~imGdOyNK z)2QRI!p$g?H`2ZtUu#yBS4`s$Jol6RCRA!1=2#GT`gKb3vpT2J>e!sL(Y)`ne^eW` za#>#C_j+!YS&*~Ca`HFM*4fiZ?>%}-YqDqDZcxUPJ3ZpxG>2Bs&AH5QT&ne5!WX66 zzg)JsSm1lz*dRpD0qv>L!fl7vp{NB-aj6mtEb43Rl@(XEPuz(7y77$s=f>1YU4UmBpa7Z?k{KNUCsSP znV-iq$qg^0`^gK(6Bn~k9$acQ>V>Z`SzMe;a&G9kIPvu0 z@CuFa0Kp{Bmu;$Ss~(zEu4wd`(O*42SZ7bHvP?^6_xC`VUjt0H~dO~goODdxw&i5kms7bb<(@uF2-)1wirY!Xr?YM>Q^E)-Ci|gZ}KF0^0sc$xD zTZ{k7C!1;|NKV^F*&#BRlxBO!Tq8ByzP&ba+*^B(Mf=r6Bi092(GiZxXvV-zltt8=cm*6li3t>We)dc3?uJmQYDyUvrAhni2`hOXUC zQSeo-OaH8njlQ%})%m!S<3BGc)!*N{`u0NI#gzJA&)Vs_wrX&jJo8Cy=sxL!Rdg%& z3v4*_dp0j6qe8`6OGAvC+cQ&tMI5iscYcZ*$giGdhl`Qt#Wm$(1G)~Lx>i+#w$&nz zwIqnB;5uWU<{yS8`*K=tzLJv|a{9}=#hWs_5F?@cF%i9i!RJKV`Dt$o@c;M~#v!JMG6rixQ1A6_;KQutr8ePjR5{PMBiTKpPV z<82hI@R>RRBfP)4yvc3Wd30r8*SpHGs@$s!QbOZ*N->$0m;B$&Bv`y!^tN(KZ`Um| zgz7#2aN^3at~_u)BsjygS^Mrm9hp2lr1xc5U#^62Kt<8g@lCev?VBo|k>5irZQEHh zt9F;(-~UTXfw@ucK;Gf}GYu8a?y6%;F1$taBEIAn{f}$z^PNiOR${BKyyi^W<4sK; zr$u&=W~In)b;oc+6F67yRMRdI-jp*h*KFg&#!iI2Hf%^U{KW2?Yrd`5(AMUYK0Yfw zku-Q*PNGYsiEO=^$Qhlcm{j~?h1GFcb>4fKu<~WC_}!AZ2VYLbuAZpD#`wJg3ash`yUu zP8Ibz=o0+xx*w^Z?^w<3`KK1>#&BoU-jb{rS4kYV{xlG?80`ybOTi}c{G_DJMy5{9 z%lEpKjTpk;c#0_@15)m^!n3dnv#n1s z*sVU;g3%ZS#$DQm-Z-LA0;qq@;S-#dtGT+JgEjc?FA`>Cp#Q}J2)Kh?7?#}Ft`k(i zw;wQ^xr3dxm5b|MoHbp8A&QF&^%+ciU<92RjQSg!0BY5|5PXO8r05Vj0>XERn!*Ad z8v+}NRLpX)D!OJN_=L8>zy)~ScQt1D;H2Y${p=85XFcTN=vd+_nWo znn?La7_fu`+kZlU*jQnZfJ;o|>3}e&AB%@TlifR&Harj4e|EtmvI+pl!7hhT5W@}> zh(HeN{99PrD`TH~16F6is*V61QbE6z?N$nw!N;(BEeg{?hs;Wq(V;ZlzrW1aqp(QG;dyB;vfAXuJ>(Bx}udAFG6 zzkEV<4y4CP@}W?Q2+%2U8YsU;%{fUO>QlMQIK&Z(gW<23{DTLusqj3o`@CnvUrXmiO{=1>rI zpn(oN6lNp|kqyZvvY=3h!1YoeLGsC!CU1}14msG1Zy`b~qK5#Y+yQVWSW}M&(b!~K zBzPQwR09+c+Ta@(%**D`6%q+|k3i^Q4BzIMLA%c(-6v`Z_rl|Th&;$+p(hYs9hS}R zq2?NcKym?rgr(~RMx~f%mZL1H@OImmV>ra zcmy_vA6WhR1KIceLcoBz5?ZxX$zqHe5l_Pq20SbO;fD2xW1L$$)#mdE6v_wzZmWR) z>9b%YV!U&xhLDY}27Z$R36)zLiFQj7L_-xAa*>gJw&sU*R*$3@iImuFc_l!@1_2y= zfv0aoLPQ~cW8?72~u0C%RDvQ)GTrravL&Zv;r|n zqzi&0Xop4`f%%{)qx|NSg4vb(n`!bNqa?S6R>=??T2ES`mZ9Ck9KcC%N5-NA1VMPT H!Ds&m&yBEs diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e318290e619bb6..b6517bb1d16502 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,3 @@ -#Mon Jan 16 11:21:59 CST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 27309d92314c57..cccdd3d517fc52 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -33,11 +33,11 @@ DEFAULT_JVM_OPTS="" # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -154,11 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index f6d5974e72fdac..e95643d6a2ca62 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -49,7 +49,6 @@ goto fail @rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +59,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line diff --git a/local-cli/templates/HelloWorld/android/build.gradle b/local-cli/templates/HelloWorld/android/build.gradle index 49569e4db5f7e7..3ad24c19027c10 100644 --- a/local-cli/templates/HelloWorld/android/build.gradle +++ b/local-cli/templates/HelloWorld/android/build.gradle @@ -38,3 +38,8 @@ ext { targetSdkVersion = 26 supportLibVersion = "26.1.0" } + +task wrapper(type: Wrapper) { + gradleVersion = '4.4' + distributionUrl = distributionUrl.replace("bin", "all") +} diff --git a/local-cli/templates/HelloWorld/android/gradle/wrapper/gradle-wrapper.jar b/local-cli/templates/HelloWorld/android/gradle/wrapper/gradle-wrapper.jar index b5166dad4d90021f6a0b45268c0755719f1d5cd4..01b8bf6b1f99cad9213fc495b33ad5bbab8efd20 100644 GIT binary patch delta 42314 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

!I{ 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 MR6yud!{M+00Sm=Wj{pDw diff --git a/local-cli/templates/HelloWorld/android/gradlew b/local-cli/templates/HelloWorld/android/gradlew index 91a7e269e19dfc..cccdd3d517fc52 100755 --- a/local-cli/templates/HelloWorld/android/gradlew +++ b/local-cli/templates/HelloWorld/android/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -6,20 +6,38 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -30,6 +48,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,31 +59,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -90,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -114,6 +113,7 @@ fi if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` @@ -154,11 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/local-cli/templates/HelloWorld/android/gradlew.bat b/local-cli/templates/HelloWorld/android/gradlew.bat index aec99730b4e8fc..e95643d6a2ca62 100644 --- a/local-cli/templates/HelloWorld/android/gradlew.bat +++ b/local-cli/templates/HelloWorld/android/gradlew.bat @@ -8,14 +8,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome @@ -46,10 +46,9 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +59,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line From 657b1d2a7aa5f5b7c5984b79d0904725f67b1b80 Mon Sep 17 00:00:00 2001 From: Eli White Date: Wed, 8 Aug 2018 14:50:58 -0700 Subject: [PATCH 021/273] Move Switch native require call to new file Summary: Moving out the requireNativeComponent call into a new file. We want this long term for all of our view managers to support codegen of the native side and so we can move the viewConfigs into JS. Reviewed By: yungsters Differential Revision: D9191214 fbshipit-source-id: d0bddbb50bb1cf6b5a727d72faf834b007ad9440 --- Libraries/Components/Switch/Switch.js | 50 +++-------------- .../Switch/SwitchNativeComponent.js | 56 +++++++++++++++++++ 2 files changed, 64 insertions(+), 42 deletions(-) create mode 100644 Libraries/Components/Switch/SwitchNativeComponent.js diff --git a/Libraries/Components/Switch/Switch.js b/Libraries/Components/Switch/Switch.js index b400588a61f3b5..0e11aff4e5e817 100644 --- a/Libraries/Components/Switch/Switch.js +++ b/Libraries/Components/Switch/Switch.js @@ -10,16 +10,15 @@ 'use strict'; +const SwitchNativeComponent = require('SwitchNativeComponent'); const Platform = require('Platform'); const React = require('React'); -const ReactNative = require('ReactNative'); const StyleSheet = require('StyleSheet'); -const requireNativeComponent = require('requireNativeComponent'); - import type {SwitchChangeEvent} from 'CoreEventTypes'; import type {ColorValue} from 'StyleSheetTypes'; import type {ViewProps} from 'ViewPropTypes'; +import type {NativeAndroidProps, NativeIOSProps} from 'SwitchNativeComponent'; export type Props = $ReadOnly<{| ...ViewProps, @@ -75,41 +74,6 @@ export type Props = $ReadOnly<{| onValueChange?: ?(value: boolean) => Promise | void, |}>; -// @see ReactSwitchManager.java -type NativeAndroidProps = $ReadOnly<{| - ...ViewProps, - enabled?: ?boolean, - on?: ?boolean, - onChange?: ?(event: SwitchChangeEvent) => mixed, - thumbTintColor?: ?string, - trackTintColor?: ?string, -|}>; - -// @see RCTSwitchManager.m -type NativeIOSProps = $ReadOnly<{| - ...ViewProps, - disabled?: ?boolean, - onChange?: ?(event: SwitchChangeEvent) => mixed, - onTintColor?: ?string, - thumbTintColor?: ?string, - tintColor?: ?string, - value?: ?boolean, -|}>; - -type NativeSwitchType = Class< - ReactNative.NativeComponent< - $ReadOnly<{| - ...NativeAndroidProps, - ...NativeIOSProps, - |}>, - >, ->; - -const NativeSwitch: NativeSwitchType = - Platform.OS === 'android' - ? (requireNativeComponent('AndroidSwitch'): any) - : (requireNativeComponent('RCTSwitch'): any); - /** * A visual toggle between two mutually exclusive states. * @@ -119,7 +83,7 @@ const NativeSwitch: NativeSwitchType = * supplied `value` prop instead of the expected result of any user actions. */ class Switch extends React.Component { - _nativeSwitchRef: ?React.ElementRef; + _nativeSwitchRef: ?React.ElementRef; render() { const { @@ -197,13 +161,13 @@ class Switch extends React.Component { }: NativeIOSProps); return ( - ); } @@ -230,7 +194,9 @@ class Switch extends React.Component { } }; - _handleNativeSwitchRef = (ref: ?React.ElementRef) => { + _handleSwitchNativeComponentRef = ( + ref: ?React.ElementRef, + ) => { this._nativeSwitchRef = ref; }; } diff --git a/Libraries/Components/Switch/SwitchNativeComponent.js b/Libraries/Components/Switch/SwitchNativeComponent.js new file mode 100644 index 00000000000000..3810e0ce335127 --- /dev/null +++ b/Libraries/Components/Switch/SwitchNativeComponent.js @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + */ + +'use strict'; + +const Platform = require('Platform'); +const ReactNative = require('ReactNative'); + +const requireNativeComponent = require('requireNativeComponent'); + +import type {SwitchChangeEvent} from 'CoreEventTypes'; +import type {ViewProps} from 'ViewPropTypes'; + +// @see ReactSwitchManager.java +export type NativeAndroidProps = $ReadOnly<{| + ...ViewProps, + enabled?: ?boolean, + on?: ?boolean, + onChange?: ?(event: SwitchChangeEvent) => mixed, + thumbTintColor?: ?string, + trackTintColor?: ?string, +|}>; + +// @see RCTSwitchManager.m +export type NativeIOSProps = $ReadOnly<{| + ...ViewProps, + disabled?: ?boolean, + onChange?: ?(event: SwitchChangeEvent) => mixed, + onTintColor?: ?string, + thumbTintColor?: ?string, + tintColor?: ?string, + value?: ?boolean, +|}>; + +type SwitchNativeComponentType = Class< + ReactNative.NativeComponent< + $ReadOnly<{| + ...NativeAndroidProps, + ...NativeIOSProps, + |}>, + >, +>; + +const SwitchNativeComponent: SwitchNativeComponentType = + Platform.OS === 'android' + ? (requireNativeComponent('AndroidSwitch'): any) + : (requireNativeComponent('RCTSwitch'): any); + +module.exports = SwitchNativeComponent; From 36440ff4b576b79dadf319e37958b33a5855eafd Mon Sep 17 00:00:00 2001 From: rainywan Date: Wed, 8 Aug 2018 18:12:57 -0700 Subject: [PATCH 022/273] =?UTF-8?q?remove=20code=20relating=20to=20Nesting?= =?UTF-8?q?=20of=20=20within=20,=20which=20result=E2=80=A6=20(?= =?UTF-8?q?#20558)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: …s a crash in Text Example of RNTester. Thank you for sending the PR! We appreciate you spending the time to work on these changes. Help us understand your motivation by explaining why you decided to make this change. If this PR fixes an issue, type "Fixes #issueNumber" to automatically close the issue when the PR is merged. Pull Request resolved: https://github.com/facebook/react-native/pull/20558 Differential Revision: D9235009 Pulled By: hramos fbshipit-source-id: 23ed28f7c8b84f509d35ac0fe7aa72c183a9ab11 --- RNTester/js/TextExample.ios.js | 64 ---------------------------------- 1 file changed, 64 deletions(-) diff --git a/RNTester/js/TextExample.ios.js b/RNTester/js/TextExample.ios.js index 52274d7c032c16..b0a1ccd696800c 100644 --- a/RNTester/js/TextExample.ios.js +++ b/RNTester/js/TextExample.ios.js @@ -255,25 +255,6 @@ class TextBaseLineLayoutExample extends React.Component<*, *> { {marker} - {'Interleaving and :'} - - {marker} - - Some text. - - {marker} - Text inside View. - {marker} - - - {marker} - - {':'} {marker} @@ -750,26 +731,6 @@ exports.examples = [ ); }, }, - { - title: 'Inline views', - render: function() { - return ( - - - This text contains an inline blue view{' '} - {' '} - and an inline image{' '} - . Neat, huh? - - - ); - }, - }, { title: 'Text shadow', render: function() { @@ -843,31 +804,6 @@ exports.examples = [ ); }, }, - { - title: 'Nested content', - render: function() { - return ( - - This text has a view - - which has - - another text inside. - - - And moreover, it has another view - - - with another text inside! - - - - - Because we need to go deeper. - - ); - }, - }, { title: 'Dynamic Font Size Adjustment', render: function(): React.Element { From 7ad4d23409e78d202d3fd1454b035bf4a7c5a8f1 Mon Sep 17 00:00:00 2001 From: Steven Cable Date: Wed, 8 Aug 2018 18:24:47 -0700 Subject: [PATCH 023/273] Check return code from malloc (#20173) Summary: Calls abort() in cases where malloc returns NULL. Checking the return value from malloc is good practice and is required to pass a [Veracode security scan](https://www.veracode.com/). This will let developers who are required to submit their software to Veracode use React Native. Pull Request resolved: https://github.com/facebook/react-native/pull/20173 Differential Revision: D9235096 Pulled By: hramos fbshipit-source-id: 9fdc97f9e84f8d4d91ae59242093907f7a81d286 --- Libraries/Image/RCTImageBlurUtils.m | 12 ++++++++++++ Libraries/Network/RCTNetworking.mm | 6 ++++++ React/Base/RCTModuleMethod.mm | 6 ++++++ React/Profiler/RCTProfile.m | 18 ++++++++++-------- React/Views/RCTComponentData.m | 6 ++++++ 5 files changed, 40 insertions(+), 8 deletions(-) diff --git a/Libraries/Image/RCTImageBlurUtils.m b/Libraries/Image/RCTImageBlurUtils.m index 84c90019bfbcc9..c35cf984793d60 100644 --- a/Libraries/Image/RCTImageBlurUtils.m +++ b/Libraries/Image/RCTImageBlurUtils.m @@ -35,6 +35,12 @@ size_t bytes = buffer1.rowBytes * buffer1.height; buffer1.data = malloc(bytes); buffer2.data = malloc(bytes); + if (!buffer1.data || !buffer2.data) { + // CWE - 391 : Unchecked error condition + // https://www.cvedetails.com/cwe-details/391/Unchecked-Error-Condition.html + // https://eli.thegreenplace.net/2009/10/30/handling-out-of-memory-conditions-in-c + abort(); + } // A description of how to compute the box kernel width from the Gaussian // radius (aka standard deviation) appears in the SVG spec: @@ -45,6 +51,12 @@ //create temp buffer void *tempBuffer = malloc((size_t)vImageBoxConvolve_ARGB8888(&buffer1, &buffer2, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend + kvImageGetTempBufferSize)); + if (!tempBuffer) { + // CWE - 391 : Unchecked error condition + // https://www.cvedetails.com/cwe-details/391/Unchecked-Error-Condition.html + // https://eli.thegreenplace.net/2009/10/30/handling-out-of-memory-conditions-in-c + abort(); + } //copy image data CFDataRef dataSource = CGDataProviderCopyData(CGImageGetDataProvider(imageRef)); diff --git a/Libraries/Network/RCTNetworking.mm b/Libraries/Network/RCTNetworking.mm index e7e5ad88c6a8a3..2b4d4dd8975260 100644 --- a/Libraries/Network/RCTNetworking.mm +++ b/Libraries/Network/RCTNetworking.mm @@ -50,6 +50,12 @@ @implementation RCTHTTPFormDataHelper const char *boundaryChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_."; char *bytes = (char*)malloc(boundaryLength); + if (!bytes) { + // CWE - 391 : Unchecked error condition + // https://www.cvedetails.com/cwe-details/391/Unchecked-Error-Condition.html + // https://eli.thegreenplace.net/2009/10/30/handling-out-of-memory-conditions-in-c + abort(); + } size_t charCount = strlen(boundaryChars); for (int i = 0; i < boundaryLength; i++) { bytes[i] = boundaryChars[arc4random_uniform((u_int32_t)charCount)]; diff --git a/React/Base/RCTModuleMethod.mm b/React/Base/RCTModuleMethod.mm index 1a151577914724..e121240b339fad 100644 --- a/React/Base/RCTModuleMethod.mm +++ b/React/Base/RCTModuleMethod.mm @@ -302,6 +302,12 @@ - (void)processMethodSignature [argumentBlocks addObject:^(__unused RCTBridge *bridge, NSUInteger index, id json) { void *returnValue = malloc(typeSignature.methodReturnLength); + if (!returnValue) { + // CWE - 391 : Unchecked error condition + // https://www.cvedetails.com/cwe-details/391/Unchecked-Error-Condition.html + // https://eli.thegreenplace.net/2009/10/30/handling-out-of-memory-conditions-in-c + abort(); + } [typeInvocation setArgument:&json atIndex:2]; [typeInvocation invoke]; [typeInvocation getReturnValue:returnValue]; diff --git a/React/Profiler/RCTProfile.m b/React/Profiler/RCTProfile.m index 3b255505800c1f..5b899eb465440d 100644 --- a/React/Profiler/RCTProfile.m +++ b/React/Profiler/RCTProfile.m @@ -76,14 +76,16 @@ } systrace_arg_t *systrace_args = malloc(sizeof(systrace_arg_t) * args.count); - __block size_t i = 0; - [args enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, __unused BOOL *stop) { - systrace_args[i].key = [key UTF8String]; - systrace_args[i].key_len = [key length]; - systrace_args[i].value = [value UTF8String]; - systrace_args[i].value_len = [value length]; - i++; - }]; + if (systrace_args) { + __block size_t i = 0; + [args enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, __unused BOOL *stop) { + systrace_args[i].key = [key UTF8String]; + systrace_args[i].key_len = [key length]; + systrace_args[i].value = [value UTF8String]; + systrace_args[i].value_len = [value length]; + i++; + }]; + } return systrace_args; } diff --git a/React/Views/RCTComponentData.m b/React/Views/RCTComponentData.m index 06bfdbaf2c2501..d1b51648e93a19 100644 --- a/React/Views/RCTComponentData.m +++ b/React/Views/RCTComponentData.m @@ -167,6 +167,12 @@ static RCTPropBlock createNSInvocationSetter(NSMethodSignature *typeSignature, S if (json) { freeValueOnCompletion = YES; value = malloc(typeSignature.methodReturnLength); + if (!value) { + // CWE - 391 : Unchecked error condition + // https://www.cvedetails.com/cwe-details/391/Unchecked-Error-Condition.html + // https://eli.thegreenplace.net/2009/10/30/handling-out-of-memory-conditions-in-c + abort(); + } [typeInvocation setArgument:&json atIndex:2]; [typeInvocation invoke]; [typeInvocation getReturnValue:value]; From 73340256279ed999b320ef627eb98a308b06f18c Mon Sep 17 00:00:00 2001 From: Johannes Baldursson Date: Wed, 8 Aug 2018 18:32:18 -0700 Subject: [PATCH 024/273] Exposed scrollEnabled on TextInput (#19330) Summary: On iOS, it is not possible to select a range of text using a `Text` component (see #13938). Because of how the `Text` component is implemented on iOS, this will not work without a complete re-write. On Android however, this is not an issue. As the `TextInput` component has evolved, it can more or less be used as a drop-in replacement on iOS by setting `multiline={true}` and `editable={false}`. Except for one detail: the text input field has scrolling activated and it's not possible to turn off. (See #1391 and #15962). This pull request addresses that issue, simply by exposing the `scrollEnabled` property: ``` ``` 1. Create a multiline `TextInput` component, with the attributes presented above. 2. Run on iOS 3. The `TextInput` field should not be able to scroll facebook/react-native-website#367 [IOS] [FEATURE] [TextInput] - Made it possible to turn off scrolling on a multiline TextInput component Pull Request resolved: https://github.com/facebook/react-native/pull/19330 Differential Revision: D9235061 Pulled By: hramos fbshipit-source-id: 99d278004fc236b47dde7e61d74c71e8a3b9d170 --- Libraries/Components/TextInput/TextInput.js | 6 ++++++ Libraries/Text/TextInput/RCTBaseTextInputViewManager.m | 1 + 2 files changed, 7 insertions(+) diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index 178821b3ad7042..162119b5506960 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -581,6 +581,12 @@ const TextInput = createReactClass({ * The text color of the placeholder string. */ placeholderTextColor: ColorPropType, + /** + * If `false`, scrolling of the text view will be disabled. + * The default value is `true`. Does only work with 'multiline={true}'. + * @platform ios + */ + scrollEnabled: PropTypes.bool, /** * If `true`, the text input obscures the text entered so that sensitive text * like passwords stay secure. The default value is `false`. Does not work with 'multiline={true}'. diff --git a/Libraries/Text/TextInput/RCTBaseTextInputViewManager.m b/Libraries/Text/TextInput/RCTBaseTextInputViewManager.m index d5c49328042812..9d0789b450a9f0 100644 --- a/Libraries/Text/TextInput/RCTBaseTextInputViewManager.m +++ b/Libraries/Text/TextInput/RCTBaseTextInputViewManager.m @@ -48,6 +48,7 @@ @implementation RCTBaseTextInputViewManager RCT_REMAP_VIEW_PROPERTY(spellCheck, backedTextInputView.spellCheckingType, UITextSpellCheckingType) RCT_REMAP_VIEW_PROPERTY(caretHidden, backedTextInputView.caretHidden, BOOL) RCT_REMAP_VIEW_PROPERTY(clearButtonMode, backedTextInputView.clearButtonMode, UITextFieldViewMode) +RCT_REMAP_VIEW_PROPERTY(scrollEnabled, backedTextInputView.scrollEnabled, BOOL) RCT_EXPORT_VIEW_PROPERTY(blurOnSubmit, BOOL) RCT_EXPORT_VIEW_PROPERTY(clearTextOnFocus, BOOL) RCT_EXPORT_VIEW_PROPERTY(keyboardType, UIKeyboardType) From a535cc9c0670b6ae8802c2a9f887e623b4cdc5e5 Mon Sep 17 00:00:00 2001 From: Eli White Date: Wed, 8 Aug 2018 18:34:26 -0700 Subject: [PATCH 025/273] Move View native require call to new file Summary: Moving out the requireNativeComponent call into a new file. We want this long term for all of our view managers to support codegen of the native side and so we can move the viewConfigs into JS. Reviewed By: yungsters Differential Revision: D9231619 fbshipit-source-id: 7c89587cc6a76e92b309c4941577291e56af8c7c --- Libraries/Components/View/View.js | 17 ++++++------- .../Components/View/ViewNativeComponent.js | 25 +++++++++++++++++++ 2 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 Libraries/Components/View/ViewNativeComponent.js diff --git a/Libraries/Components/View/View.js b/Libraries/Components/View/View.js index 2cfa05a8c118b2..35c0bfa4e8cec4 100644 --- a/Libraries/Components/View/View.js +++ b/Libraries/Components/View/View.js @@ -12,11 +12,10 @@ const React = require('React'); const TextAncestor = require('TextAncestor'); +const ViewNativeComponent = require('ViewNativeComponent'); const invariant = require('fbjs/lib/invariant'); -const requireNativeComponent = require('requireNativeComponent'); -import type {NativeComponent} from 'ReactNative'; import type {ViewProps} from 'ViewPropTypes'; export type Props = ViewProps; @@ -28,11 +27,13 @@ export type Props = ViewProps; * * @see http://facebook.github.io/react-native/docs/view.html */ -const RCTView = requireNativeComponent('RCTView'); -let ViewToExport = RCTView; +let ViewToExport = ViewNativeComponent; if (__DEV__) { - const View = (props: Props, forwardedRef: ?React.Ref<'RCTView'>) => { + const View = ( + props: Props, + forwardedRef: React.Ref, + ) => { return ( {hasTextAncestor => { @@ -40,7 +41,7 @@ if (__DEV__) { !hasTextAncestor, 'Nesting of within is not currently supported.', ); - return ; + return ; }} ); @@ -49,6 +50,4 @@ if (__DEV__) { ViewToExport = React.forwardRef(View); } -module.exports = ((ViewToExport: $FlowFixMe): Class< - NativeComponent, ->); +module.exports = ((ViewToExport: $FlowFixMe): typeof ViewNativeComponent); diff --git a/Libraries/Components/View/ViewNativeComponent.js b/Libraries/Components/View/ViewNativeComponent.js new file mode 100644 index 00000000000000..728e81beb419cb --- /dev/null +++ b/Libraries/Components/View/ViewNativeComponent.js @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow + */ + +'use strict'; + +const ReactNative = require('ReactNative'); + +const requireNativeComponent = require('requireNativeComponent'); + +import type {ViewProps} from 'ViewPropTypes'; + +type ViewNativeComponentType = Class>; + +const ViewNativeComponent = ((requireNativeComponent( + 'RCTView', +): any): ViewNativeComponentType); + +module.exports = ViewNativeComponent; From cc6978f396701fe47775a1b95bc9062cd39ddc73 Mon Sep 17 00:00:00 2001 From: Justin Chapman Date: Wed, 8 Aug 2018 21:01:23 -0700 Subject: [PATCH 026/273] Allow for undefined userConfig (#18660) Summary: Fixes #18249 This PR fixes an error that occurs when running `react-native link` in projects laid out as described on the React Native website section on integrating with existing apps (https://facebook.github.io/react-native/docs/integration-with-existing-apps.html) where an `ios/` subdirectory exists but an `android/` subdirectory does not exist screenshot 2018-04-02 14 57 27 None [CLI] [BUGFIX] [local-cli/core/android/index.js] - Allow for undefined userConfig Pull Request resolved: https://github.com/facebook/react-native/pull/18660 Differential Revision: D9235171 Pulled By: hramos fbshipit-source-id: 230dd54f8911046f7e01633f99c4f02070fa0172 --- local-cli/core/__tests__/android/getProjectConfig.spec.js | 7 +++++++ local-cli/core/android/index.js | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/local-cli/core/__tests__/android/getProjectConfig.spec.js b/local-cli/core/__tests__/android/getProjectConfig.spec.js index 02ee04512a4245..594f4d13a326de 100644 --- a/local-cli/core/__tests__/android/getProjectConfig.spec.js +++ b/local-cli/core/__tests__/android/getProjectConfig.spec.js @@ -37,6 +37,13 @@ describe('android::getProjectConfig', () => { }); }); + it("returns `null` if manifest file hasn't been found and userConfig is not defined", () => { + const userConfig = undefined; + const folder = '/noManifest'; + + expect(getProjectConfig(folder, userConfig)).toBeNull(); + }); + it("returns `null` if manifest file hasn't been found", () => { const userConfig = {}; const folder = '/noManifest'; diff --git a/local-cli/core/android/index.js b/local-cli/core/android/index.js index 914341a1223453..f8e5586eb6e867 100644 --- a/local-cli/core/android/index.js +++ b/local-cli/core/android/index.js @@ -21,7 +21,7 @@ const getPackageName = manifest => manifest.attr.package; * Gets android project config by analyzing given folder and taking some * defaults specified by user into consideration */ -exports.projectConfig = function projectConfigAndroid(folder, userConfig) { +exports.projectConfig = function projectConfigAndroid(folder, userConfig = {}) { const src = userConfig.sourceDir || findAndroidAppFolder(folder); if (!src) { @@ -95,7 +95,7 @@ exports.projectConfig = function projectConfigAndroid(folder, userConfig) { */ exports.dependencyConfig = function dependencyConfigAndroid( folder, - userConfig, + userConfig = {}, ) { const src = userConfig.sourceDir || findAndroidAppFolder(folder); From 43ded753b162561fea1d114a578a062f9efab535 Mon Sep 17 00:00:00 2001 From: Wayne Cheng Date: Thu, 9 Aug 2018 08:32:04 -0700 Subject: [PATCH 027/273] Adding flow strict local to remaining possible files in xplat/JS Summary: ag -L --ignore __snapshots__ 'flow strict|noflow|generated|The controller you requested could not be found.' | ag '\.js$' | xargs ag -l 'flow' | sort > ~/temp cat ~/temp | xargs ag -L 'flow strict' | xargs sed -i '' 's/flow$/flow strict-local/' until flow check; do flow check --json | jq -r '.errors[].message[0].path' | sort | uniq | xargs hg revert; done allow_many_files The controller you requested could not be found. The controller you requested could not be found. Reviewed By: TheSavior Differential Revision: D9004573 fbshipit-source-id: 936bd5741706b781be06bf08b6ad805a69407dfd --- IntegrationTests/AccessibilityManagerTest.js | 2 +- IntegrationTests/ImageCachePolicyTest.js | 2 +- IntegrationTests/ImageSnapshotTest.js | 2 +- IntegrationTests/SyncMethodTest.js | 2 +- Libraries/Alert/RCTAlertManager.ios.js | 2 +- Libraries/Animated/src/Animated.js | 2 +- Libraries/Animated/src/AnimatedWeb.js | 2 +- Libraries/Animated/src/nodes/AnimatedWithChildren.js | 2 +- Libraries/BatchedBridge/BatchedBridge.js | 2 +- Libraries/Blob/BlobManager.js | 2 +- Libraries/Blob/URL.js | 2 +- Libraries/Components/CheckBox/CheckBox.ios.js | 2 +- Libraries/Components/Clipboard/Clipboard.js | 2 +- .../Components/RefreshControl/__mocks__/RefreshControlMock.js | 2 +- Libraries/Components/StatusBar/StatusBarIOS.ios.js | 2 +- Libraries/Components/TextInput/TextInputState.js | 2 +- Libraries/Components/UnimplementedViews/UnimplementedView.js | 2 +- Libraries/Components/View/PlatformViewPropTypes.js | 2 +- Libraries/Components/View/View.js | 2 +- Libraries/Core/Devtools/openFileInEditor.js | 2 +- Libraries/Core/ReactNativeVersionCheck.js | 2 +- Libraries/EventEmitter/RCTNativeAppEventEmitter.js | 2 +- Libraries/Experimental/SwipeableRow/SwipeableQuickActions.js | 2 +- Libraries/Inspector/BorderBox.js | 2 +- Libraries/Inspector/BoxInspector.js | 2 +- Libraries/Inspector/ElementBox.js | 2 +- Libraries/Inspector/InspectorPanel.js | 2 +- Libraries/Inspector/StyleInspector.js | 2 +- Libraries/Interaction/Batchinator.js | 2 +- Libraries/Interaction/FrameRateLogger.js | 2 +- Libraries/Interaction/InteractionStallDebugger.js | 2 +- Libraries/JSInspector/JSInspector.js | 2 +- Libraries/Lists/ListView/__mocks__/ListViewMock.js | 2 +- Libraries/Lists/__flowtests__/FlatList-flowtest.js | 2 +- Libraries/Performance/SamplingProfiler.js | 2 +- Libraries/ReactNative/I18nManager.js | 2 +- Libraries/ReactNative/UIManager.js | 2 +- Libraries/ReactNative/UIManagerStatTracker.js | 2 +- Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js | 2 +- Libraries/Renderer/shims/createReactNativeComponentClass.js | 2 +- Libraries/Sample/Sample.ios.js | 2 +- Libraries/StyleSheet/StyleSheetPropType.js | 2 +- Libraries/StyleSheet/StyleSheetTypes.js | 2 +- Libraries/StyleSheet/flattenStyle.js | 2 +- Libraries/StyleSheet/processColor.js | 2 +- Libraries/UTFSequence.js | 2 +- Libraries/Utilities/DeviceInfo.js | 2 +- Libraries/Utilities/HMRLoadingView.ios.js | 2 +- Libraries/Utilities/HeapCapture.js | 2 +- Libraries/Utilities/JSDevSupportModule.js | 2 +- Libraries/Utilities/PixelRatio.js | 2 +- Libraries/Utilities/deprecatedPropType.js | 2 +- Libraries/Vibration/VibrationIOS.ios.js | 2 +- Libraries/YellowBox/UI/YellowBoxImageSource.js | 2 +- Libraries/YellowBox/UI/YellowBoxInspectorSourceMapStatus.js | 2 +- Libraries/vendor/emitter/EventSubscription.js | 2 +- RNTester/js/ActivityIndicatorExample.js | 2 +- RNTester/js/AssetScaledImageExample.js | 2 +- RNTester/js/ButtonExample.js | 2 +- RNTester/js/ClipboardExample.js | 2 +- RNTester/js/ImageCapInsetsExample.js | 2 +- RNTester/js/ImageExample.js | 2 +- RNTester/js/LayoutExample.js | 2 +- RNTester/js/ListViewExample.js | 2 +- RNTester/js/ListViewGridLayoutExample.js | 2 +- RNTester/js/MaskedViewExample.js | 2 +- RNTester/js/ModalExample.js | 2 +- RNTester/js/PickerExample.js | 2 +- RNTester/js/RNTesterSettingSwitchRow.js | 2 +- RNTester/js/RNTesterTitle.js | 2 +- RNTester/js/SafeAreaViewExample.js | 2 +- RNTester/js/SetPropertiesExampleApp.js | 2 +- RNTester/js/StatusBarExample.js | 2 +- RNTester/js/TabBarIOSBarStyleExample.js | 2 +- RNTester/js/TabBarIOSExample.js | 2 +- RNTester/js/ToolbarAndroidExample.ios.js | 2 +- RNTester/js/VibrationExample.js | 2 +- RNTester/js/VibrationIOSExample.js | 2 +- RNTester/js/ViewExample.js | 2 +- RNTester/js/XHRExampleBinaryUpload.js | 2 +- ReactAndroid/src/androidTest/js/NativeIdTestModule.js | 2 +- lib/InitializeJavaScriptAppEngine.js | 2 +- lib/RCTEventEmitter.js | 2 +- lib/TextInputState.js | 2 +- lib/UIManager.js | 2 +- lib/UIManagerStatTracker.js | 2 +- lib/View.js | 2 +- lib/deepDiffer.js | 2 +- lib/deepFreezeAndThrowOnMutationInDev.js | 2 +- lib/flattenStyle.js | 2 +- local-cli/bundle/types.flow.js | 2 +- local-cli/server/server.js | 2 +- local-cli/templates/HelloWorld/App.js | 2 +- 93 files changed, 93 insertions(+), 93 deletions(-) diff --git a/IntegrationTests/AccessibilityManagerTest.js b/IntegrationTests/AccessibilityManagerTest.js index 41710be91e14c0..50c2c1c2c301e5 100644 --- a/IntegrationTests/AccessibilityManagerTest.js +++ b/IntegrationTests/AccessibilityManagerTest.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/IntegrationTests/ImageCachePolicyTest.js b/IntegrationTests/ImageCachePolicyTest.js index 1dc5d5fb61a9b5..52d1be1d03ea03 100644 --- a/IntegrationTests/ImageCachePolicyTest.js +++ b/IntegrationTests/ImageCachePolicyTest.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/IntegrationTests/ImageSnapshotTest.js b/IntegrationTests/ImageSnapshotTest.js index c20406c641ecb5..0da33f62718a3f 100644 --- a/IntegrationTests/ImageSnapshotTest.js +++ b/IntegrationTests/ImageSnapshotTest.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/IntegrationTests/SyncMethodTest.js b/IntegrationTests/SyncMethodTest.js index 6efef977d81194..0b912396813027 100644 --- a/IntegrationTests/SyncMethodTest.js +++ b/IntegrationTests/SyncMethodTest.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Alert/RCTAlertManager.ios.js b/Libraries/Alert/RCTAlertManager.ios.js index 529bb5da0e55f2..dd561eec3a13f7 100644 --- a/Libraries/Alert/RCTAlertManager.ios.js +++ b/Libraries/Alert/RCTAlertManager.ios.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Animated/src/Animated.js b/Libraries/Animated/src/Animated.js index 5b831396c3fc74..1c60f253f903de 100644 --- a/Libraries/Animated/src/Animated.js +++ b/Libraries/Animated/src/Animated.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ diff --git a/Libraries/Animated/src/AnimatedWeb.js b/Libraries/Animated/src/AnimatedWeb.js index e80023d73687a4..5bf1fdb0e184a0 100644 --- a/Libraries/Animated/src/AnimatedWeb.js +++ b/Libraries/Animated/src/AnimatedWeb.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Animated/src/nodes/AnimatedWithChildren.js b/Libraries/Animated/src/nodes/AnimatedWithChildren.js index 9cd5fb49e14070..01189a482fae52 100644 --- a/Libraries/Animated/src/nodes/AnimatedWithChildren.js +++ b/Libraries/Animated/src/nodes/AnimatedWithChildren.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ 'use strict'; diff --git a/Libraries/BatchedBridge/BatchedBridge.js b/Libraries/BatchedBridge/BatchedBridge.js index 0b1aae766493e6..1c5bb4f4c8f516 100644 --- a/Libraries/BatchedBridge/BatchedBridge.js +++ b/Libraries/BatchedBridge/BatchedBridge.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Blob/BlobManager.js b/Libraries/Blob/BlobManager.js index b08082e35e1580..6677019411aeac 100644 --- a/Libraries/Blob/BlobManager.js +++ b/Libraries/Blob/BlobManager.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ diff --git a/Libraries/Blob/URL.js b/Libraries/Blob/URL.js index de73affac2af1b..de59323c784071 100644 --- a/Libraries/Blob/URL.js +++ b/Libraries/Blob/URL.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Components/CheckBox/CheckBox.ios.js b/Libraries/Components/CheckBox/CheckBox.ios.js index 5fda2cd5ec2bce..11252120daa166 100644 --- a/Libraries/Components/CheckBox/CheckBox.ios.js +++ b/Libraries/Components/CheckBox/CheckBox.ios.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ 'use strict'; diff --git a/Libraries/Components/Clipboard/Clipboard.js b/Libraries/Components/Clipboard/Clipboard.js index 706bc0fba8c9b7..a8096b26a0770b 100644 --- a/Libraries/Components/Clipboard/Clipboard.js +++ b/Libraries/Components/Clipboard/Clipboard.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Components/RefreshControl/__mocks__/RefreshControlMock.js b/Libraries/Components/RefreshControl/__mocks__/RefreshControlMock.js index bc03b7afa87878..8e85742ce4c4da 100644 --- a/Libraries/Components/RefreshControl/__mocks__/RefreshControlMock.js +++ b/Libraries/Components/RefreshControl/__mocks__/RefreshControlMock.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Components/StatusBar/StatusBarIOS.ios.js b/Libraries/Components/StatusBar/StatusBarIOS.ios.js index 529e01b308fd88..ed8ef0f4a1ca11 100644 --- a/Libraries/Components/StatusBar/StatusBarIOS.ios.js +++ b/Libraries/Components/StatusBar/StatusBarIOS.ios.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Components/TextInput/TextInputState.js b/Libraries/Components/TextInput/TextInputState.js index 66682e40a40ade..05a7b4bf4366a7 100644 --- a/Libraries/Components/TextInput/TextInputState.js +++ b/Libraries/Components/TextInput/TextInputState.js @@ -10,7 +10,7 @@ * should be funneled through here * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Components/UnimplementedViews/UnimplementedView.js b/Libraries/Components/UnimplementedViews/UnimplementedView.js index 7be6f1ac77f759..ec21fde54492b2 100644 --- a/Libraries/Components/UnimplementedViews/UnimplementedView.js +++ b/Libraries/Components/UnimplementedViews/UnimplementedView.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ 'use strict'; diff --git a/Libraries/Components/View/PlatformViewPropTypes.js b/Libraries/Components/View/PlatformViewPropTypes.js index 4c6105893cc6eb..f74be145353819 100644 --- a/Libraries/Components/View/PlatformViewPropTypes.js +++ b/Libraries/Components/View/PlatformViewPropTypes.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ const Platform = require('Platform'); diff --git a/Libraries/Components/View/View.js b/Libraries/Components/View/View.js index 35c0bfa4e8cec4..0ec2fda48fc79c 100644 --- a/Libraries/Components/View/View.js +++ b/Libraries/Components/View/View.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Core/Devtools/openFileInEditor.js b/Libraries/Core/Devtools/openFileInEditor.js index c085883920aeda..eedf9f1233d68d 100644 --- a/Libraries/Core/Devtools/openFileInEditor.js +++ b/Libraries/Core/Devtools/openFileInEditor.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Core/ReactNativeVersionCheck.js b/Libraries/Core/ReactNativeVersionCheck.js index 8a937c769d9979..623ae4f3536b19 100644 --- a/Libraries/Core/ReactNativeVersionCheck.js +++ b/Libraries/Core/ReactNativeVersionCheck.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ 'use strict'; diff --git a/Libraries/EventEmitter/RCTNativeAppEventEmitter.js b/Libraries/EventEmitter/RCTNativeAppEventEmitter.js index a32cfcef7cf9c7..fcf5ae86438887 100644 --- a/Libraries/EventEmitter/RCTNativeAppEventEmitter.js +++ b/Libraries/EventEmitter/RCTNativeAppEventEmitter.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Experimental/SwipeableRow/SwipeableQuickActions.js b/Libraries/Experimental/SwipeableRow/SwipeableQuickActions.js index 3642b135d43191..8178770c882d29 100644 --- a/Libraries/Experimental/SwipeableRow/SwipeableQuickActions.js +++ b/Libraries/Experimental/SwipeableRow/SwipeableQuickActions.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Inspector/BorderBox.js b/Libraries/Inspector/BorderBox.js index b172871df8e2f2..2110953dd36029 100644 --- a/Libraries/Inspector/BorderBox.js +++ b/Libraries/Inspector/BorderBox.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Inspector/BoxInspector.js b/Libraries/Inspector/BoxInspector.js index af373460053609..f2b5e44df433b9 100644 --- a/Libraries/Inspector/BoxInspector.js +++ b/Libraries/Inspector/BoxInspector.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Inspector/ElementBox.js b/Libraries/Inspector/ElementBox.js index dea05dad737894..ee7ccdf3259b8f 100644 --- a/Libraries/Inspector/ElementBox.js +++ b/Libraries/Inspector/ElementBox.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Inspector/InspectorPanel.js b/Libraries/Inspector/InspectorPanel.js index 2793452d90e578..d1b6d0eaf003bf 100644 --- a/Libraries/Inspector/InspectorPanel.js +++ b/Libraries/Inspector/InspectorPanel.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Inspector/StyleInspector.js b/Libraries/Inspector/StyleInspector.js index 0f06cd40f6b686..af58645d3c69a3 100644 --- a/Libraries/Inspector/StyleInspector.js +++ b/Libraries/Inspector/StyleInspector.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Interaction/Batchinator.js b/Libraries/Interaction/Batchinator.js index eea02e45ed3fe2..cb16a97d05555a 100644 --- a/Libraries/Interaction/Batchinator.js +++ b/Libraries/Interaction/Batchinator.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Interaction/FrameRateLogger.js b/Libraries/Interaction/FrameRateLogger.js index b9d872e80ff960..b675ccb017e7c5 100644 --- a/Libraries/Interaction/FrameRateLogger.js +++ b/Libraries/Interaction/FrameRateLogger.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Interaction/InteractionStallDebugger.js b/Libraries/Interaction/InteractionStallDebugger.js index 899eee0ec1143a..d17e775d7868f6 100644 --- a/Libraries/Interaction/InteractionStallDebugger.js +++ b/Libraries/Interaction/InteractionStallDebugger.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/JSInspector/JSInspector.js b/Libraries/JSInspector/JSInspector.js index 21ccf7fbc1510c..0983cd7799b8b2 100644 --- a/Libraries/JSInspector/JSInspector.js +++ b/Libraries/JSInspector/JSInspector.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Lists/ListView/__mocks__/ListViewMock.js b/Libraries/Lists/ListView/__mocks__/ListViewMock.js index a691136be39a4f..5e766a75708382 100644 --- a/Libraries/Lists/ListView/__mocks__/ListViewMock.js +++ b/Libraries/Lists/ListView/__mocks__/ListViewMock.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ 'use strict'; diff --git a/Libraries/Lists/__flowtests__/FlatList-flowtest.js b/Libraries/Lists/__flowtests__/FlatList-flowtest.js index d8cbd75a153db4..de52ce482e1f92 100644 --- a/Libraries/Lists/__flowtests__/FlatList-flowtest.js +++ b/Libraries/Lists/__flowtests__/FlatList-flowtest.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ diff --git a/Libraries/Performance/SamplingProfiler.js b/Libraries/Performance/SamplingProfiler.js index 6dcda029c5505d..1bb87f2a78766b 100644 --- a/Libraries/Performance/SamplingProfiler.js +++ b/Libraries/Performance/SamplingProfiler.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/ReactNative/I18nManager.js b/Libraries/ReactNative/I18nManager.js index 5212d1100dac92..7611891959386d 100644 --- a/Libraries/ReactNative/I18nManager.js +++ b/Libraries/ReactNative/I18nManager.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ 'use strict'; diff --git a/Libraries/ReactNative/UIManager.js b/Libraries/ReactNative/UIManager.js index d137f757b326f7..a3e084e9345a93 100644 --- a/Libraries/ReactNative/UIManager.js +++ b/Libraries/ReactNative/UIManager.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ 'use strict'; diff --git a/Libraries/ReactNative/UIManagerStatTracker.js b/Libraries/ReactNative/UIManagerStatTracker.js index f0f47f1b3e227d..8c26e8484e435f 100644 --- a/Libraries/ReactNative/UIManagerStatTracker.js +++ b/Libraries/ReactNative/UIManagerStatTracker.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ 'use strict'; diff --git a/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js b/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js index 44a7f1827da6d4..1ef2e80e371a44 100644 --- a/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js +++ b/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Renderer/shims/createReactNativeComponentClass.js b/Libraries/Renderer/shims/createReactNativeComponentClass.js index 4ea7d2818378fe..33e708b7c388ce 100644 --- a/Libraries/Renderer/shims/createReactNativeComponentClass.js +++ b/Libraries/Renderer/shims/createReactNativeComponentClass.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Sample/Sample.ios.js b/Libraries/Sample/Sample.ios.js index 6c7443201667f8..856ba1a3d62408 100644 --- a/Libraries/Sample/Sample.ios.js +++ b/Libraries/Sample/Sample.ios.js @@ -7,7 +7,7 @@ * Stub of Sample for Android. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/StyleSheet/StyleSheetPropType.js b/Libraries/StyleSheet/StyleSheetPropType.js index 964c91b5d4d33f..97674b9a1e4f33 100644 --- a/Libraries/StyleSheet/StyleSheetPropType.js +++ b/Libraries/StyleSheet/StyleSheetPropType.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/StyleSheet/StyleSheetTypes.js b/Libraries/StyleSheet/StyleSheetTypes.js index 41cab5de3b42a2..685d095434b321 100644 --- a/Libraries/StyleSheet/StyleSheetTypes.js +++ b/Libraries/StyleSheet/StyleSheetTypes.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ diff --git a/Libraries/StyleSheet/flattenStyle.js b/Libraries/StyleSheet/flattenStyle.js index cb5f6ebc96e71f..9fabc4bebd37b3 100644 --- a/Libraries/StyleSheet/flattenStyle.js +++ b/Libraries/StyleSheet/flattenStyle.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ 'use strict'; diff --git a/Libraries/StyleSheet/processColor.js b/Libraries/StyleSheet/processColor.js index 77ba69ded17eb3..a261cb42c5be90 100644 --- a/Libraries/StyleSheet/processColor.js +++ b/Libraries/StyleSheet/processColor.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/UTFSequence.js b/Libraries/UTFSequence.js index 5c450cd2bdcfef..6792bbf6e2eaf5 100644 --- a/Libraries/UTFSequence.js +++ b/Libraries/UTFSequence.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ diff --git a/Libraries/Utilities/DeviceInfo.js b/Libraries/Utilities/DeviceInfo.js index 88b2a896167f8f..8ed4dd31895392 100644 --- a/Libraries/Utilities/DeviceInfo.js +++ b/Libraries/Utilities/DeviceInfo.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Utilities/HMRLoadingView.ios.js b/Libraries/Utilities/HMRLoadingView.ios.js index 631df2c2f8193a..a349407f23bb10 100644 --- a/Libraries/Utilities/HMRLoadingView.ios.js +++ b/Libraries/Utilities/HMRLoadingView.ios.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Utilities/HeapCapture.js b/Libraries/Utilities/HeapCapture.js index 999cb869b30d4e..0b91c4ecc6cac0 100644 --- a/Libraries/Utilities/HeapCapture.js +++ b/Libraries/Utilities/HeapCapture.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Utilities/JSDevSupportModule.js b/Libraries/Utilities/JSDevSupportModule.js index 074ebef6b19fbb..943cf83a574f4f 100644 --- a/Libraries/Utilities/JSDevSupportModule.js +++ b/Libraries/Utilities/JSDevSupportModule.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Utilities/PixelRatio.js b/Libraries/Utilities/PixelRatio.js index 0c6386e31a2c68..3982be19a1120d 100644 --- a/Libraries/Utilities/PixelRatio.js +++ b/Libraries/Utilities/PixelRatio.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Utilities/deprecatedPropType.js b/Libraries/Utilities/deprecatedPropType.js index 7421b44e950476..1083fe1222090d 100644 --- a/Libraries/Utilities/deprecatedPropType.js +++ b/Libraries/Utilities/deprecatedPropType.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/Vibration/VibrationIOS.ios.js b/Libraries/Vibration/VibrationIOS.ios.js index 6f1c95c9a2944b..3b26e228f38a4a 100644 --- a/Libraries/Vibration/VibrationIOS.ios.js +++ b/Libraries/Vibration/VibrationIOS.ios.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/Libraries/YellowBox/UI/YellowBoxImageSource.js b/Libraries/YellowBox/UI/YellowBoxImageSource.js index 1d3fc2e979c7fc..dca95fa8231631 100644 --- a/Libraries/YellowBox/UI/YellowBoxImageSource.js +++ b/Libraries/YellowBox/UI/YellowBoxImageSource.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ diff --git a/Libraries/YellowBox/UI/YellowBoxInspectorSourceMapStatus.js b/Libraries/YellowBox/UI/YellowBoxInspectorSourceMapStatus.js index 831305d74ea5bc..b0552d52840aec 100644 --- a/Libraries/YellowBox/UI/YellowBoxInspectorSourceMapStatus.js +++ b/Libraries/YellowBox/UI/YellowBoxInspectorSourceMapStatus.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ diff --git a/Libraries/vendor/emitter/EventSubscription.js b/Libraries/vendor/emitter/EventSubscription.js index 3b1052ab403b18..c3af23932c2bf7 100644 --- a/Libraries/vendor/emitter/EventSubscription.js +++ b/Libraries/vendor/emitter/EventSubscription.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/ActivityIndicatorExample.js b/RNTester/js/ActivityIndicatorExample.js index 2f81857cfcfdb0..27528dbb76e2e4 100644 --- a/RNTester/js/ActivityIndicatorExample.js +++ b/RNTester/js/ActivityIndicatorExample.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/AssetScaledImageExample.js b/RNTester/js/AssetScaledImageExample.js index d3a295a27e8277..1cc618217f58c7 100644 --- a/RNTester/js/AssetScaledImageExample.js +++ b/RNTester/js/AssetScaledImageExample.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/ButtonExample.js b/RNTester/js/ButtonExample.js index 45b0ff2dd65d56..6d93b8286e2f82 100644 --- a/RNTester/js/ButtonExample.js +++ b/RNTester/js/ButtonExample.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/ClipboardExample.js b/RNTester/js/ClipboardExample.js index 13309df37493c7..c8c74ac6a3805e 100644 --- a/RNTester/js/ClipboardExample.js +++ b/RNTester/js/ClipboardExample.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/ImageCapInsetsExample.js b/RNTester/js/ImageCapInsetsExample.js index 76705f4d7e60d9..1ba1c9aad680f0 100644 --- a/RNTester/js/ImageCapInsetsExample.js +++ b/RNTester/js/ImageCapInsetsExample.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/ImageExample.js b/RNTester/js/ImageExample.js index 0dc3b30b96572f..6672195e92b8ec 100644 --- a/RNTester/js/ImageExample.js +++ b/RNTester/js/ImageExample.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/LayoutExample.js b/RNTester/js/LayoutExample.js index 3803fcf9002810..89be190775ac99 100644 --- a/RNTester/js/LayoutExample.js +++ b/RNTester/js/LayoutExample.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/ListViewExample.js b/RNTester/js/ListViewExample.js index a274c353949f59..ffc73b78726106 100644 --- a/RNTester/js/ListViewExample.js +++ b/RNTester/js/ListViewExample.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/ListViewGridLayoutExample.js b/RNTester/js/ListViewGridLayoutExample.js index 65a407f4d19e90..d4d0cc063ab9b1 100644 --- a/RNTester/js/ListViewGridLayoutExample.js +++ b/RNTester/js/ListViewGridLayoutExample.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/MaskedViewExample.js b/RNTester/js/MaskedViewExample.js index b944fbc16f7366..516eb206f3b8f0 100644 --- a/RNTester/js/MaskedViewExample.js +++ b/RNTester/js/MaskedViewExample.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/ModalExample.js b/RNTester/js/ModalExample.js index a66d331d03c9cc..ddacc829c3ebde 100644 --- a/RNTester/js/ModalExample.js +++ b/RNTester/js/ModalExample.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/PickerExample.js b/RNTester/js/PickerExample.js index 0fd21fc7de32ea..c156c7f19c7fc6 100644 --- a/RNTester/js/PickerExample.js +++ b/RNTester/js/PickerExample.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/RNTesterSettingSwitchRow.js b/RNTester/js/RNTesterSettingSwitchRow.js index 423ccf23b24288..d7b68f8bdf6724 100644 --- a/RNTester/js/RNTesterSettingSwitchRow.js +++ b/RNTester/js/RNTesterSettingSwitchRow.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/RNTesterTitle.js b/RNTester/js/RNTesterTitle.js index 39d36a3a029f92..ae163b83f40817 100644 --- a/RNTester/js/RNTesterTitle.js +++ b/RNTester/js/RNTesterTitle.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/SafeAreaViewExample.js b/RNTester/js/SafeAreaViewExample.js index be7ce97fa3b6aa..6035481d7a68d4 100644 --- a/RNTester/js/SafeAreaViewExample.js +++ b/RNTester/js/SafeAreaViewExample.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ 'use strict'; diff --git a/RNTester/js/SetPropertiesExampleApp.js b/RNTester/js/SetPropertiesExampleApp.js index 2b8e3fe5bf26e8..0773be00b80352 100644 --- a/RNTester/js/SetPropertiesExampleApp.js +++ b/RNTester/js/SetPropertiesExampleApp.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/StatusBarExample.js b/RNTester/js/StatusBarExample.js index 3247567111c9a6..e66e94a605db1d 100644 --- a/RNTester/js/StatusBarExample.js +++ b/RNTester/js/StatusBarExample.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/TabBarIOSBarStyleExample.js b/RNTester/js/TabBarIOSBarStyleExample.js index d6a035aed3e151..0fd00eaad5f366 100644 --- a/RNTester/js/TabBarIOSBarStyleExample.js +++ b/RNTester/js/TabBarIOSBarStyleExample.js @@ -17,7 +17,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/TabBarIOSExample.js b/RNTester/js/TabBarIOSExample.js index 38fcbc64f81505..16f69e9a7cf2ae 100644 --- a/RNTester/js/TabBarIOSExample.js +++ b/RNTester/js/TabBarIOSExample.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/ToolbarAndroidExample.ios.js b/RNTester/js/ToolbarAndroidExample.ios.js index 25bf7dba0fe729..6ad678f53665e8 100644 --- a/RNTester/js/ToolbarAndroidExample.ios.js +++ b/RNTester/js/ToolbarAndroidExample.ios.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/VibrationExample.js b/RNTester/js/VibrationExample.js index ed12bd1e5491f7..c4760d78130b3e 100644 --- a/RNTester/js/VibrationExample.js +++ b/RNTester/js/VibrationExample.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/VibrationIOSExample.js b/RNTester/js/VibrationIOSExample.js index 59e96b673977a0..b63d136d7c0372 100644 --- a/RNTester/js/VibrationIOSExample.js +++ b/RNTester/js/VibrationIOSExample.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/ViewExample.js b/RNTester/js/ViewExample.js index 5115a08d5ac785..89ce92d3f19510 100644 --- a/RNTester/js/ViewExample.js +++ b/RNTester/js/ViewExample.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/RNTester/js/XHRExampleBinaryUpload.js b/RNTester/js/XHRExampleBinaryUpload.js index 1321522ccaf75c..211c2f3ca1707d 100644 --- a/RNTester/js/XHRExampleBinaryUpload.js +++ b/RNTester/js/XHRExampleBinaryUpload.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/ReactAndroid/src/androidTest/js/NativeIdTestModule.js b/ReactAndroid/src/androidTest/js/NativeIdTestModule.js index eb791c356d1201..daec9a252ee42e 100644 --- a/ReactAndroid/src/androidTest/js/NativeIdTestModule.js +++ b/ReactAndroid/src/androidTest/js/NativeIdTestModule.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/lib/InitializeJavaScriptAppEngine.js b/lib/InitializeJavaScriptAppEngine.js index 5048f860e41d0e..266704de7e3778 100644 --- a/lib/InitializeJavaScriptAppEngine.js +++ b/lib/InitializeJavaScriptAppEngine.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/lib/RCTEventEmitter.js b/lib/RCTEventEmitter.js index c225257d105cb4..da4996b9ddcdaf 100644 --- a/lib/RCTEventEmitter.js +++ b/lib/RCTEventEmitter.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/lib/TextInputState.js b/lib/TextInputState.js index 5345311a518d31..e76510adb6db3f 100644 --- a/lib/TextInputState.js +++ b/lib/TextInputState.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/lib/UIManager.js b/lib/UIManager.js index b846967b626fa7..56e45cdd91e240 100644 --- a/lib/UIManager.js +++ b/lib/UIManager.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/lib/UIManagerStatTracker.js b/lib/UIManagerStatTracker.js index c62aebdf0aee88..bd5da422215062 100644 --- a/lib/UIManagerStatTracker.js +++ b/lib/UIManagerStatTracker.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/lib/View.js b/lib/View.js index 852e741251bd7f..4ff92230f2d978 100644 --- a/lib/View.js +++ b/lib/View.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/lib/deepDiffer.js b/lib/deepDiffer.js index 6254047d472671..c1fd4dd3598289 100644 --- a/lib/deepDiffer.js +++ b/lib/deepDiffer.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/lib/deepFreezeAndThrowOnMutationInDev.js b/lib/deepFreezeAndThrowOnMutationInDev.js index 6691d2a648b1a2..37583d73d4a039 100644 --- a/lib/deepFreezeAndThrowOnMutationInDev.js +++ b/lib/deepFreezeAndThrowOnMutationInDev.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/lib/flattenStyle.js b/lib/flattenStyle.js index 1c7256c7fca7e0..c68ae561c4f6ef 100644 --- a/lib/flattenStyle.js +++ b/lib/flattenStyle.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/local-cli/bundle/types.flow.js b/local-cli/bundle/types.flow.js index 3fb3d930ee1bbb..6fbd570daf6eb3 100644 --- a/local-cli/bundle/types.flow.js +++ b/local-cli/bundle/types.flow.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/local-cli/server/server.js b/local-cli/server/server.js index 4865cbcc7a6920..5862af217b72e6 100644 --- a/local-cli/server/server.js +++ b/local-cli/server/server.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ 'use strict'; diff --git a/local-cli/templates/HelloWorld/App.js b/local-cli/templates/HelloWorld/App.js index 171d0f0f4a8532..db41976f413c26 100644 --- a/local-cli/templates/HelloWorld/App.js +++ b/local-cli/templates/HelloWorld/App.js @@ -3,7 +3,7 @@ * https://github.com/facebook/react-native * * @format - * @flow + * @flow strict-local */ import React, {Component} from 'react'; From bcae5b7d8fd329f0fd87a25e2164f186c52cbbc8 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 9 Aug 2018 10:46:04 -0700 Subject: [PATCH 028/273] Add flow strict typing to isEmpty Summary: Add flow strict typing to the isEmpty lib Reviewed By: wcheng86 Differential Revision: D9200520 fbshipit-source-id: ac5717216199166e7485abcdfcba03ab2bbe90d2 --- Libraries/vendor/core/isEmpty.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Libraries/vendor/core/isEmpty.js b/Libraries/vendor/core/isEmpty.js index f8b4eb2c96b0fd..e3b9e128fb54af 100644 --- a/Libraries/vendor/core/isEmpty.js +++ b/Libraries/vendor/core/isEmpty.js @@ -4,6 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * + * @flow strict * @format */ @@ -12,7 +13,7 @@ /** * Mimics empty from PHP. */ -function isEmpty(obj) { +function isEmpty(obj: mixed): boolean { if (Array.isArray(obj)) { return obj.length === 0; } else if (typeof obj === 'object') { From e4f66944a7265307838d39e1fad8fbe8758af7b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Unneb=C3=A4ck?= Date: Thu, 9 Aug 2018 11:10:11 -0700 Subject: [PATCH 029/273] Properly escape JavaScript code on Android (#20366) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: These changes will fix executing javascript with any special characters, by making use of the `evaluateJavascript` function on Android 4.4+, and by properly escaping the URI on Android <4.4. Fixes #19611 • Fixes #20365 • Fixes #9749 • Closes #19655 • Closes #12321 This PR supersedes #19655 by patching the same problem in all the places, and fixing it for Android <4.4 as well. Pull Request resolved: https://github.com/facebook/react-native/pull/20366 Differential Revision: D9242968 Pulled By: hramos fbshipit-source-id: f2e1abc786ba333dbd8aaa8922e716fd99ec26e0 --- .../views/webview/ReactWebViewManager.java | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java index 6bcc4e1857fc09..6e55b80f8c3e5a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java @@ -16,6 +16,7 @@ import javax.annotation.Nullable; import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; import java.util.ArrayList; import java.util.HashMap; import java.util.Locale; @@ -325,11 +326,25 @@ public void setMessagingEnabled(boolean enabled) { } } + protected void evaluateJavascriptWithFallback(String script) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + evaluateJavascript(script, null); + return; + } + + try { + loadUrl("javascript:" + URLEncoder.encode(script, "UTF-8")); + } catch (UnsupportedEncodingException e) { + // UTF-8 should always be supported + throw new RuntimeException(e); + } + } + public void callInjectedJavaScript() { if (getSettings().getJavaScriptEnabled() && injectedJS != null && !TextUtils.isEmpty(injectedJS)) { - loadUrl("javascript:(function() {\n" + injectedJS + ";\n})();"); + evaluateJavascriptWithFallback("(function() {\n" + injectedJS + ";\n})();"); } } @@ -348,7 +363,7 @@ public void onReceiveValue(String value) { }); } - loadUrl("javascript:(" + + evaluateJavascriptWithFallback("(" + "window.originalPostMessage = window.postMessage," + "window.postMessage = function(data) {" + BRIDGE_NAME + ".postMessage(String(data));" + @@ -637,9 +652,10 @@ public void receiveCommand(WebView root, int commandId, @Nullable ReadableArray break; case COMMAND_POST_MESSAGE: try { + ReactWebView reactWebView = (ReactWebView) root; JSONObject eventInitDict = new JSONObject(); eventInitDict.put("data", args.getString(0)); - root.loadUrl("javascript:(function () {" + + reactWebView.evaluateJavascriptWithFallback("(function () {" + "var event;" + "var data = " + eventInitDict.toString() + ";" + "try {" + @@ -655,7 +671,8 @@ public void receiveCommand(WebView root, int commandId, @Nullable ReadableArray } break; case COMMAND_INJECT_JAVASCRIPT: - root.loadUrl("javascript:" + args.getString(0)); + ReactWebView reactWebView = (ReactWebView) root; + reactWebView.evaluateJavascriptWithFallback(args.getString(0)); break; } } From f5b126f1c961af4d604e619a5760ef564d739091 Mon Sep 17 00:00:00 2001 From: Kevin Gozali Date: Thu, 9 Aug 2018 12:16:19 -0700 Subject: [PATCH 030/273] iOS: prevent nativemodule access from JS if bridge is no longer valid Summary: This helps prevent race condition where JS calls to NativeModules got queued and executed while the bridge is invalidating itself, causing assertion failures in test setup (for example). It won't prevent it 100% of the time, due to threading (and adding lock is expensive for each nativemodule call). Reviewed By: yungsters Differential Revision: D9231636 fbshipit-source-id: 298eaf52ffa4b84108184124e75b206b9ca7a41d --- Libraries/RCTTest/RCTTestRunner.m | 41 +++++++++++++++++++----------- React/CxxModule/RCTNativeModule.mm | 15 +++++++---- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/Libraries/RCTTest/RCTTestRunner.m b/Libraries/RCTTest/RCTTestRunner.m index 65e126ae8c169a..6d572a104f26b9 100644 --- a/Libraries/RCTTest/RCTTestRunner.m +++ b/Libraries/RCTTest/RCTTestRunner.m @@ -115,20 +115,20 @@ - (void)runTest:(SEL)test module:(NSString *)moduleName { __weak RCTBridge *batchedBridge; NSNumber *rootTag; - - @autoreleasepool { - __block NSMutableArray *errors = nil; - RCTLogFunction defaultLogFunction = RCTGetLogFunction(); - RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { - defaultLogFunction(level, source, fileName, lineNumber, message); - if (level >= RCTLogLevelError) { - if (errors == nil) { - errors = [NSMutableArray new]; - } - [errors addObject:message]; + RCTLogFunction defaultLogFunction = RCTGetLogFunction(); + // Catch all error logs, that are equivalent to redboxes in dev mode. + __block NSMutableArray *errors = nil; + RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { + defaultLogFunction(level, source, fileName, lineNumber, message); + if (level >= RCTLogLevelError) { + if (errors == nil) { + errors = [NSMutableArray new]; } - }); + [errors addObject:message]; + } + }); + @autoreleasepool { RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:_scriptURL moduleProvider:_moduleProvider launchOptions:nil]; @@ -172,7 +172,16 @@ - (void)runTest:(SEL)test module:(NSString *)moduleName testModule.view = nil; } - RCTSetLogFunction(defaultLogFunction); + // From this point on catch only fatal errors. + RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { + defaultLogFunction(level, source, fileName, lineNumber, message); + if (level >= RCTLogLevelFatal) { + if (errors == nil) { + errors = [NSMutableArray new]; + } + [errors addObject:message]; + } + }); #if RCT_DEV NSArray *nonLayoutSubviews = [vc.view.subviews filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id subview, NSDictionary *bindings) { @@ -208,8 +217,10 @@ - (void)runTest:(SEL)test module:(NSString *)moduleName [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; } - // Note: this deallocation isn't consistently working in test setup, so disable the assertion. - // RCTAssert(batchedBridge == nil, @"Bridge should be deallocated after the test"); + RCTAssert(errors == nil, @"RedBox errors during bridge invalidation: %@", errors); + RCTAssert(batchedBridge == nil, @"Bridge should be deallocated after the test"); + + RCTSetLogFunction(defaultLogFunction); } @end diff --git a/React/CxxModule/RCTNativeModule.mm b/React/CxxModule/RCTNativeModule.mm index 077b729789d29b..8cf3b74db431cc 100644 --- a/React/CxxModule/RCTNativeModule.mm +++ b/React/CxxModule/RCTNativeModule.mm @@ -71,11 +71,16 @@ invokeInner(weakBridge, weakModuleData, methodId, std::move(params)); }; - dispatch_queue_t queue = m_moduleData.methodQueue; - if (queue == RCTJSThread) { - block(); - } else if (queue) { - dispatch_async(queue, block); + if (m_bridge.valid) { + dispatch_queue_t queue = m_moduleData.methodQueue; + if (queue == RCTJSThread) { + block(); + } else if (queue) { + dispatch_async(queue, block); + } + } else { + RCTLogError(@"Attempted to invoke `%u` (method ID) on `%@` (NativeModule name) with an invalid bridge.", + methodId, m_moduleData.name); } } From d99bb768fdd48f8be264df6e3f50f9f1bae5309a Mon Sep 17 00:00:00 2001 From: Dexter Date: Thu, 9 Aug 2018 12:36:33 -0700 Subject: [PATCH 031/273] Fix memory usage display in Perf Monitor (#19664) Summary: According to: https://github.com/apple/darwin-xnu/blob/master/osfmk/kern/bsd_kern.c#L420 The result is the same as Xcode app memory uesd. Before Fix: before before1 After Fix: after after1 [IOS] [BUGFIX] [Monitor] - fix memory perf monitor. Make sure the memory footprint is the same as Jetsam. Pull Request resolved: https://github.com/facebook/react-native/pull/19664 Differential Revision: D9246307 Pulled By: hramos fbshipit-source-id: f85efc54cdcb0c19677594d465752c666d5af18b --- React/Profiler/RCTPerfMonitor.m | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/React/Profiler/RCTPerfMonitor.m b/React/Profiler/RCTPerfMonitor.m index 768142437b0bd5..b9c2c4cd585152 100644 --- a/React/Profiler/RCTPerfMonitor.m +++ b/React/Profiler/RCTPerfMonitor.m @@ -62,17 +62,14 @@ static BOOL RCTJSCSetOption(const char *option) static vm_size_t RCTGetResidentMemorySize(void) { - struct task_basic_info info; - mach_msg_type_number_t size = sizeof(info); - kern_return_t kerr = task_info(mach_task_self(), - TASK_BASIC_INFO, - (task_info_t)&info, - &size); - if (kerr != KERN_SUCCESS) { - return 0; - } - - return info.resident_size; + vm_size_t memoryUsageInByte = 0; + task_vm_info_data_t vmInfo; + mach_msg_type_number_t count = TASK_VM_INFO_COUNT; + kern_return_t kernelReturn = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count); + if(kernelReturn == KERN_SUCCESS) { + memoryUsageInByte = (vm_size_t) vmInfo.phys_footprint; + } + return memoryUsageInByte; } @interface RCTPerfMonitor : NSObject From 245a84c14119a7f9d0308bf2906f32dfa800274b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Thu, 9 Aug 2018 16:15:19 -0700 Subject: [PATCH 032/273] Check Flow and run basic packager tests using open source RN config Summary: Most of the changes associated with this commit will not be visible on GitHub, as they concern files in the internal Facebook monorepo. The bulk of this change is the addition of a new test that runs on the internal test infrastructure. The actual script used by the test has various references to the internal test infra, but a copy is produced below with some changes that should allow it to run on open source should anyone be interested in testing this outside of Facebook. The test has the main goal of catching common sources of FB-to-GitHub breakages, such as the OSS Flow config falling out of date (we use a different flow config than what is synced out in .flowconfig, and hence internally we rename this file to .github.flowconfig). It also checks that the packager can run on a brand new project, among other things. ``` set -e THIS_DIR=$(pwd) REACT_NATIVE_TEMP_DIR=$(mktemp -d /tmp/react-native-XXXXXXXX) REACT_NATIVE_APP_TEMP_DIR=$(mktemp -d /tmp/react-native-XXXXXXXX) OFFLINE_MIRROR=$(yarn config get yarn-offline-mirror) function describe { printf "\\n\\n>>>>> %s\\n\\n\\n" "$1" } function cleanup { set +e rm -rf "$REACT_NATIVE_TEMP_DIR" rm -rf "$REACT_NATIVE_APP_TEMP_DIR" rm "$OFFLINE_MIRROR/react-native-v1000.0.0.tgz" set -e } trap cleanup EXIT describe "Creating temporary react-native-github clone" cp -R "react-native" "$REACT_NATIVE_TEMP_DIR" pushd "$REACT_NATIVE_TEMP_DIR/react-native" >/dev/null echo yarn-offline-mirror="$OFFLINE_MIRROR" > .npmrc describe "Installing react-native node_modules from offline cache" yarn install --mutex network --offline --frozen-lockfile --ignore-engines --ignore-scripts 2>&1 describe "Running a Flow check" mv .github.flowconfig .flowconfig ./node_modules/.bin/flow check describe "Running a basic packager test" touch .watchmanconfig node local-cli/cli.js bundle --platform android --dev true --entry-file ReactAndroid/src/androidTest/js/TestBundle.js --bundle-output ReactAndroid/src/androidTest/assets/AndroidTestBundle.js describe "Creating package for e2e test" yarn pack REACT_NATIVE_PACKAGE="$(pwd)/react-native-v1000.0.0.tgz" REACT_VERSION=$(node -p -e "require('./package.json').peerDependencies['react']") REACT_NATIVE_HASH=$(shasum "$REACT_NATIVE_PACKAGE" | awk '{print $1;}') REACT_NATIVE_DEPS=$(node -p -e "const deps=require('./package.json').dependencies; ' ' + Object.keys(deps).map(dep => dep + ' \"' + deps[dep] +'\"').join('\n ')") popd >/dev/null describe "Installing temporary RN app" mkdir "$REACT_NATIVE_APP_TEMP_DIR/PackagerTest" pushd "$REACT_NATIVE_APP_TEMP_DIR/PackagerTest" >/dev/null cp "$REACT_NATIVE_PACKAGE" ./ cp "$REACT_NATIVE_PACKAGE" "$OFFLINE_MIRROR" cp "$REACT_NATIVE_TEMP_DIR/react-native/.npmrc" ./ cp "$REACT_NATIVE_TEMP_DIR/react-native/yarn.lock" ./ cat <> yarn.lock react-native@1000.0.0: version "1000.0.0" resolved react-native-v1000.0.0.tgz#$REACT_NATIVE_HASH dependencies: $REACT_NATIVE_DEPS LOCKFILE cat > package.json <<- EndOfFile { "name": "packager-test", "version": "0.0.1", "private": true, "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start" }, "dependencies": { "react": "$REACT_VERSION", "react-native": "1000.0.0" } } EndOfFile yarn install --mutex network --offline --frozen-lockfile --ignore-engines --ignore-scripts 2>&1 sed -e s/"HelloWorld"/PackagerTest/g "react-native/local-cli/templates/HelloWorld/app.json" > app.json cp "react-native/local-cli/templates/HelloWorld/_buckconfig" .buckconfig cp "react-native/local-cli/templates/HelloWorld/_flowconfig" .flowconfig cp "react-native/local-cli/templates/HelloWorld/_watchmanconfig" .watchmanconfig cp "react-native/local-cli/templates/HelloWorld/App.js" App.js cp "react-native/local-cli/templates/HelloWorld/index.js" index.js describe "Running a Flow check on a new RN app" flow check describe "Verifying packager can produce JS bundle for a new RN app on both platforms" node ./node_modules/react-native/local-cli/cli.js bundle --platform ios --dev true --entry-file index.js --bundle-output ios-bundle.js test -e ios-bundle.js rm ios-bundle.js node ./node_modules/react-native/local-cli/cli.js bundle --platform android --dev true --entry-file index.js --bundle-output android-bundle.js test -e android-bundle.js rm android-bundle.js popd >/dev/null ``` Reviewed By: arcanis Differential Revision: D9129463 fbshipit-source-id: a91eeaa150ae6623ee67bd758bc8a98bb31e57b8 --- .flowconfig | 2 +- .github.flowconfig.android | 4 ++-- .gitignore | 4 ---- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.flowconfig b/.flowconfig index 875fc6de979a2d..0bd9289ffb57bc 100644 --- a/.flowconfig +++ b/.flowconfig @@ -56,7 +56,6 @@ module.system.haste.name_reducers='^\(.*\)\.android$' -> '\1' module.system.haste.name_reducers='^\(.*\)\.native$' -> '\1' module.system.haste.paths.blacklist=.*/__tests__/.* module.system.haste.paths.blacklist=.*/__mocks__/.* -module.system.haste.paths.blacklist=/Libraries/Animated/src/polyfills/.* module.system.haste.paths.whitelist=/Libraries/.* module.system.haste.paths.whitelist=/RNTester/.* module.system.haste.paths.whitelist=/IntegrationTests/.* @@ -78,6 +77,7 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError [lints] all=warn +unnecessary-optional-chain=off # There is an ESLint rule for this unclear-type=off diff --git a/.github.flowconfig.android b/.github.flowconfig.android index 94e6b74c947789..83d6e2225713a9 100644 --- a/.github.flowconfig.android +++ b/.github.flowconfig.android @@ -56,7 +56,6 @@ module.system.haste.name_reducers='^\(.*\)\.android$' -> '\1' module.system.haste.name_reducers='^\(.*\)\.native$' -> '\1' module.system.haste.paths.blacklist=.*/__tests__/.* module.system.haste.paths.blacklist=.*/__mocks__/.* -module.system.haste.paths.blacklist=/Libraries/Animated/src/polyfills/.* module.system.haste.paths.whitelist=/Libraries/.* module.system.haste.paths.whitelist=/RNTester/.* module.system.haste.paths.whitelist=/IntegrationTests/.* @@ -78,6 +77,7 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError [lints] all=warn +unnecessary-optional-chain=off # There is an ESLint rule for this unclear-type=off @@ -100,4 +100,4 @@ untyped-import untyped-type-import [version] -^0.77.0 +^0.78.0 diff --git a/.gitignore b/.gitignore index 50a3ed6420a2e6..4fb4a25d15f722 100644 --- a/.gitignore +++ b/.gitignore @@ -51,10 +51,6 @@ node_modules *.log .nvm /bots/node_modules/ - -# TODO: Check in yarn.lock in open source. Right now we need to keep it out -# from the GitHub repo as importing it might conflict with internal workspaces -yarn.lock package-lock.json # OS X From e88c7a91b25c6e657854004e15ffc5cb1e178864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Unneb=C3=A4ck?= Date: Fri, 10 Aug 2018 03:01:49 -0700 Subject: [PATCH 033/273] Upgrade Babel to 7.0.0-beta.56 (#216) Summary: **Summary** This pull request bumps Babel to 7.0.0-beta.56 to incorporate the latest bugfixes from Babel. **Test plan** One way to test is to add a simple TypeScript file with a type as the default export: ```typescript export const test = 1 export default interface A {} ``` and then import that file from any other file: ```js import { test } from './typescript-test' ``` Before this would throw an error, but with the latest Babel this is now fixed. Pull Request resolved: https://github.com/facebook/metro/pull/216 Reviewed By: mjesun Differential Revision: D9216331 Pulled By: rafeca fbshipit-source-id: a48e87c3c6b2902be410395b1b4afab63cb88fec --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b429a6af95cb92..02e7626bf167e4 100644 --- a/package.json +++ b/package.json @@ -201,7 +201,7 @@ "yargs": "^9.0.0" }, "devDependencies": { - "@babel/core": "7.0.0-beta.54", + "@babel/core": "7.0.0-beta.56", "async": "^2.4.0", "babel-eslint": "9.0.0-beta.2", "babel-generator": "^6.26.0", From 80173861698495d86b577ecb636dff7e20ba5b55 Mon Sep 17 00:00:00 2001 From: Alex Dvornikov Date: Fri, 10 Aug 2018 09:26:18 -0700 Subject: [PATCH 034/273] Add REGISTER_JS_SEGMENT perf markers Reviewed By: cwdick Differential Revision: D9244289 fbshipit-source-id: 9004a0405f9622cbd0bbb837b99df32454f35bb8 --- React/CxxBridge/RCTCxxBridge.mm | 2 ++ .../com/facebook/react/bridge/ReactMarkerConstants.java | 2 ++ ReactAndroid/src/main/jni/react/jni/JReactMarker.cpp | 6 ++++++ ReactCommon/cxxreact/ReactMarker.h | 2 ++ 4 files changed, 12 insertions(+) diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm index a35425efdd1383..7d290fab551fef 100644 --- a/React/CxxBridge/RCTCxxBridge.mm +++ b/React/CxxBridge/RCTCxxBridge.mm @@ -121,6 +121,8 @@ static void registerPerformanceLoggerHooks(RCTPerformanceLogger *performanceLogg case ReactMarker::JS_BUNDLE_STRING_CONVERT_STOP: case ReactMarker::NATIVE_MODULE_SETUP_START: case ReactMarker::NATIVE_MODULE_SETUP_STOP: + case ReactMarker::REGISTER_JS_SEGMENT_START: + case ReactMarker::REGISTER_JS_SEGMENT_STOP: // These are not used on iOS. break; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactMarkerConstants.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactMarkerConstants.java index c3dffabbaa7aa8..87fdd536e6a69c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactMarkerConstants.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactMarkerConstants.java @@ -85,4 +85,6 @@ public enum ReactMarkerConstants { CREATE_MC_MODULE_END, CREATE_MC_MODULE_GET_METADATA_START, CREATE_MC_MODULE_GET_METADATA_END, + REGISTER_JS_SEGMENT_START, + REGISTER_JS_SEGMENT_STOP, } diff --git a/ReactAndroid/src/main/jni/react/jni/JReactMarker.cpp b/ReactAndroid/src/main/jni/react/jni/JReactMarker.cpp index ead1c689d121ef..64c35b12ef5a03 100644 --- a/ReactAndroid/src/main/jni/react/jni/JReactMarker.cpp +++ b/ReactAndroid/src/main/jni/react/jni/JReactMarker.cpp @@ -53,6 +53,12 @@ void JReactMarker::logPerfMarker(const ReactMarker::ReactMarkerId markerId, cons case ReactMarker::NATIVE_MODULE_SETUP_STOP: JReactMarker::logMarker("NATIVE_MODULE_SETUP_END", tag); break; + case ReactMarker::REGISTER_JS_SEGMENT_START: + JReactMarker::logMarker("REGISTER_JS_SEGMENT_START", tag); + break; + case ReactMarker::REGISTER_JS_SEGMENT_STOP: + JReactMarker::logMarker("REGISTER_JS_SEGMENT_STOP", tag); + break; case ReactMarker::NATIVE_REQUIRE_START: case ReactMarker::NATIVE_REQUIRE_STOP: // These are not used on Android. diff --git a/ReactCommon/cxxreact/ReactMarker.h b/ReactCommon/cxxreact/ReactMarker.h index 3a71579ab8f0d3..a67ed8c8e59d7c 100644 --- a/ReactCommon/cxxreact/ReactMarker.h +++ b/ReactCommon/cxxreact/ReactMarker.h @@ -23,6 +23,8 @@ enum ReactMarkerId { JS_BUNDLE_STRING_CONVERT_STOP, NATIVE_MODULE_SETUP_START, NATIVE_MODULE_SETUP_STOP, + REGISTER_JS_SEGMENT_START, + REGISTER_JS_SEGMENT_STOP }; #ifdef __APPLE__ From 8caaf5fab9479b41890f6e6920d68773889fbd3f Mon Sep 17 00:00:00 2001 From: Ives van Hoorne Date: Fri, 10 Aug 2018 09:48:34 -0700 Subject: [PATCH 035/273] Bump metro to 0.43.5 Summary: Makes it possible to use Metro in node environments Reviewed By: mjesun Differential Revision: D9267780 fbshipit-source-id: 2a534a32681f3a19659989cd24e77d4465ed2caa --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 02e7626bf167e4..10d2de07dbed69 100644 --- a/package.json +++ b/package.json @@ -169,10 +169,10 @@ "graceful-fs": "^4.1.3", "inquirer": "^3.0.6", "lodash": "^4.17.5", - "metro": "^0.43.4", - "metro-babel-register": "^0.43.4", - "metro-core": "^0.43.4", - "metro-memory-fs": "^0.43.4", + "metro": "^0.43.5", + "metro-babel-register": "^0.43.5", + "metro-core": "^0.43.5", + "metro-memory-fs": "^0.43.5", "mime": "^1.3.4", "minimist": "^1.2.0", "mkdirp": "^0.5.1", From f885710aa650b931b0d1a30251210e92a112a6c7 Mon Sep 17 00:00:00 2001 From: Freddy Harris Date: Fri, 10 Aug 2018 13:56:33 -0700 Subject: [PATCH 036/273] Fix bug rows doesn't close on scroll in a SwipeableFlatList (#18001) Summary: Fix bug `SwipeableRow`s doesn't close on Scroll in a `SwipeableFlatList` Use a SwipeableFlatList with multiple rows, open one of them, then scroll. Open row should close on scroll. [GENERAL] [BUGFIX] [SwipeableFlatList] - Fix rows doesn't close on scroll Pull Request resolved: https://github.com/facebook/react-native/pull/18001 Reviewed By: TheSavior Differential Revision: D9192387 Pulled By: tomasreimers fbshipit-source-id: f43e9614f9def5f3112327163c2b15fb45d84fb2 --- Libraries/Experimental/SwipeableRow/SwipeableFlatList.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Libraries/Experimental/SwipeableRow/SwipeableFlatList.js b/Libraries/Experimental/SwipeableRow/SwipeableFlatList.js index b01fea760dd0f4..c03bbf09252df2 100644 --- a/Libraries/Experimental/SwipeableRow/SwipeableFlatList.js +++ b/Libraries/Experimental/SwipeableRow/SwipeableFlatList.js @@ -100,6 +100,7 @@ class SwipeableFlatList extends React.Component, State> { }} onScroll={this._onScroll} renderItem={this._renderItem} + extraData={this.state} /> ); } From 1be38926c00d481c78f086b905fa3f24b1dc4ff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Fri, 10 Aug 2018 13:59:40 -0700 Subject: [PATCH 037/273] Disable failing tests (#20622) Summary: `test_detox_end_to_end` and `test_objc_end_to_end` are both failing on master. This is polluting internal diffs that do not introduce failures. As we just now started tracking Circle CI on our internal builds, I want to make sure we only nag internal diffs when the failure can actually be attributed to the diff. The failures in the e2e tests precede the Circle CI integration and are adding unnecessary noise. Going forward, we will immediately go back to a diff and push the author to fix the broken CI, so this PR is a temporary fix. Pull Request resolved: https://github.com/facebook/react-native/pull/20622 Differential Revision: D9272360 Pulled By: hramos fbshipit-source-id: 2f8d22e35d301aa7eb67ed08f6deed21bf971acd --- .circleci/config.yml | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index fd5b53d03059d9..212ac52a705f5f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -467,6 +467,7 @@ jobs: path: ~/react-native/reports/junit # Runs end to end tests (Detox) + # Disabled. test_detox_end_to_end: <<: *macos_defaults steps: @@ -674,16 +675,18 @@ workflows: requires: - checkout_code + # Disabled on master. + # End-to-end tests - - test_objc_end_to_end: - filters: *filter-ignore-gh-pages - requires: - - checkout_code + # - test_objc_end_to_end: + # filters: *filter-ignore-gh-pages + # requires: + # - checkout_code - - test_detox_end_to_end: - filters: *filter-ignore-gh-pages - requires: - - checkout_code + # - test_detox_end_to_end: + # filters: *filter-ignore-gh-pages + # requires: + # - checkout_code # Only runs on vX.X.X tags if all tests are green @@ -698,7 +701,7 @@ workflows: - test_javascript - test_objc - test_android - - test_objc_end_to_end + # - test_objc_end_to_end # Only runs on PRs analyze: From 39fc0864d9ffab766a9237b1716f259e56ddfca0 Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Fri, 10 Aug 2018 14:19:38 -0700 Subject: [PATCH 038/273] Enable metro hmr server in local-cli (#20605) Summary: The `hmrEnabled` flag was not passed to the metro runServer config which caused HMR to be broken. Pull Request resolved: https://github.com/facebook/react-native/pull/20605 Differential Revision: D9272070 Pulled By: hramos fbshipit-source-id: 3765031d9e7806be11781fba92663ce7c4ff2ffb --- local-cli/server/runServer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/local-cli/server/runServer.js b/local-cli/server/runServer.js index 784cc0cc5bd5cc..369de4783cdf87 100644 --- a/local-cli/server/runServer.js +++ b/local-cli/server/runServer.js @@ -65,6 +65,7 @@ async function runServer(args: Args, config: ConfigT) { secure: args.https, secureCert: args.cert, secureKey: args.key, + hmrEnabled: true, }); const wsProxy = webSocketProxy.attachToServer( From 03e4af6dc1e900b3729049813f24e15718a509cd Mon Sep 17 00:00:00 2001 From: Rafael Oleza Date: Mon, 13 Aug 2018 07:24:44 -0700 Subject: [PATCH 039/273] Fix passing the --reset-cache CLI argument to Metro Summary: @public While debugging a RN 0.57 blocking issue, we found that the `--reset-cache` cli arg is not being passed to Metro (more info: https://github.com/facebook/react-native/issues/20567#issuecomment-412513942). This diff fixes this issue Reviewed By: mjesun Differential Revision: D9295634 fbshipit-source-id: a53ec7abff2b7e684a1fd88c3b53ff0b54a1c3c4 --- local-cli/server/runServer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/local-cli/server/runServer.js b/local-cli/server/runServer.js index 369de4783cdf87..bad3be828d1683 100644 --- a/local-cli/server/runServer.js +++ b/local-cli/server/runServer.js @@ -57,6 +57,7 @@ async function runServer(args: Args, config: ConfigT) { config.maxWorkers = args.maxWorkers; config.server.port = args.port; config.reporter = reporter; + config.resetCache = args.resetCache; config.server.enhanceMiddleware = middleware => middlewareManager.getConnectInstance().use(middleware); From 692493bff8fecab7e916f678c4606bfdbecd260e Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Mon, 13 Aug 2018 10:14:06 -0700 Subject: [PATCH 040/273] Ensure WebViews render about:blank correctly Summary: @public This diff fixes two bugs: 1. When you load a `` with an HTML source string, HTML source doesn't render in the ``. Instead, we get this warning: https://pxl.cl/grz3. Here's what the above page should look like when correctly rendered: https://pxl.cl/grzt 2. Furthermore, you render a blank `` (i.e: with no source prop), it should display a blank page. Instead, we get this warning: https://pxl.cl/grz3 **Bugfix:** One solution I found was to ensure that `about:blank` is always whitelisted. That way, we don't ever abort navigations to blank pages, which occur when we do: ```ObjectiveC /** Line 134 in RCTWebView.m */ [_webView loadHTMLString:@"" baseURL:nil]; ``` and ```ObjectiveC /** Line 115 in RCTWebView.m */ if (html) { NSURL *baseURL = [RCTConvert NSURL:source[@"baseUrl"]]; if (!baseURL) { baseURL = [NSURL URLWithString:@"about:blank"]; } [_webView loadHTMLString:html baseURL:baseURL]; return; } ``` Reviewed By: yungsters, mmmulani Differential Revision: D9259852 fbshipit-source-id: e1b9673fcd8c3d0df77308df8c4a632a2b596bfb --- Libraries/Components/WebView/WebView.ios.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Libraries/Components/WebView/WebView.ios.js b/Libraries/Components/WebView/WebView.ios.js index 56290df97bcf94..413cae03950ff9 100644 --- a/Libraries/Components/WebView/WebView.ios.js +++ b/Libraries/Components/WebView/WebView.ios.js @@ -435,9 +435,10 @@ class WebView extends React.Component { const viewManager = nativeConfig.viewManager || RCTWebViewManager; - const compiledWhitelist = (this.props.originWhitelist || []).map( - WebViewShared.originWhitelistToRegex, - ); + const compiledWhitelist = [ + 'about:blank', + ...(this.props.originWhitelist || []), + ].map(WebViewShared.originWhitelistToRegex); const onShouldStartLoadWithRequest = (event: Event) => { let shouldStart = true; const {url} = event.nativeEvent; From 75505993f0523ebf5f1ad68ee30e91e6879b28a3 Mon Sep 17 00:00:00 2001 From: Krzysztof Magiera Date: Mon, 13 Aug 2018 10:14:31 -0700 Subject: [PATCH 041/273] Fix native animated style and transform node to call __makeNative once all the children are converted to native nodes (#20658) Summary: This PR fixes an issue I have found while playing with native animated driver nodes. I discovered the bug when using animated views that have both animated props and styles. See this snack to see an example: https://snack.expo.io/B17SFXy8Q In that example we set `opacity` and `style` props which both contain animated props. This is not an usual way to do that, as normally you would place `opacity` inside the `styles` in which case the bug won't surface. But this is only done for demo purposes and in practice the problem will occur if you have a custom native view that exposes props that are not styles and can be animated. In the above example you get this error: > Invariant Violation: Attempt to get native tag from node not marked as "native" When `opacity` is moved into `styles` container the problem no longer occurs. The problem turned out to be related to the initialization code responsible for creating native animated nodes. In all subclasses of `AnimatedWithChildren` (like `AimatedAddition`) we only call `super.__makeNative` after we call `__makeNative` method on the child nodes. This order was reversed in `AnimatedStyle` and `AnimatedTransform`. As a result when `super.__makeNative` is called in `AnimatedStyle`, we try to call `__getNativeTag` on children nodes not yet marked as native which results in the error described above ("Attempt to get native tag..."). We should instead follow the order of calling `super.__makeNative` that is used in the remaining subclasses of `AnimatedWithChildren`. Such that all the children nodes are first converted to native prior to calling superclass method. This is what this PR is changing. Pull Request resolved: https://github.com/facebook/react-native/pull/20658 Differential Revision: D9297191 Pulled By: hramos fbshipit-source-id: f5e394fb259ff514c7c1433edcb5fc89203f55e2 --- Libraries/Animated/src/nodes/AnimatedStyle.js | 2 +- Libraries/Animated/src/nodes/AnimatedTransform.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Libraries/Animated/src/nodes/AnimatedStyle.js b/Libraries/Animated/src/nodes/AnimatedStyle.js index 990b960a336805..89d959f487dfcd 100644 --- a/Libraries/Animated/src/nodes/AnimatedStyle.js +++ b/Libraries/Animated/src/nodes/AnimatedStyle.js @@ -95,13 +95,13 @@ class AnimatedStyle extends AnimatedWithChildren { } __makeNative() { - super.__makeNative(); for (const key in this._style) { const value = this._style[key]; if (value instanceof AnimatedNode) { value.__makeNative(); } } + super.__makeNative(); } __getNativeConfig(): Object { diff --git a/Libraries/Animated/src/nodes/AnimatedTransform.js b/Libraries/Animated/src/nodes/AnimatedTransform.js index 1706923394ec96..537326e58ff7c5 100644 --- a/Libraries/Animated/src/nodes/AnimatedTransform.js +++ b/Libraries/Animated/src/nodes/AnimatedTransform.js @@ -22,7 +22,6 @@ class AnimatedTransform extends AnimatedWithChildren { } __makeNative() { - super.__makeNative(); this._transforms.forEach(transform => { for (const key in transform) { const value = transform[key]; @@ -31,6 +30,7 @@ class AnimatedTransform extends AnimatedWithChildren { } } }); + super.__makeNative(); } __getValue(): $ReadOnlyArray { From 9b18b5b1cfff36028e82e6bbdc0348f6ca8efa06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Unneb=C3=A4ck?= Date: Mon, 13 Aug 2018 10:26:58 -0700 Subject: [PATCH 042/273] Switch babel preset to metro-react-native-babel-preset (#20653) Summary: Fixes #20567 Pull Request resolved: https://github.com/facebook/react-native/pull/20653 Differential Revision: D9296819 Pulled By: hramos fbshipit-source-id: 88953afb9778e3c8cde5576b068888fd882c2220 --- local-cli/init/init.js | 2 +- local-cli/templates/HelloWorld/_babelrc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/local-cli/init/init.js b/local-cli/init/init.js index d7497a4a828476..54324c152ab14d 100644 --- a/local-cli/init/init.js +++ b/local-cli/init/init.js @@ -99,7 +99,7 @@ function generateProject(destinationRoot, newProjectName, options) { }); } if (!options['skip-jest']) { - const jestDeps = `jest babel-jest babel-preset-react-native@^5 react-test-renderer@${reactVersion}`; + const jestDeps = `jest babel-jest metro-react-native-babel-preset@^0.43.5 react-test-renderer@${reactVersion}`; if (yarnVersion) { console.log('Adding Jest...'); execSync(`yarn add ${jestDeps} --dev --exact`, {stdio: 'inherit'}); diff --git a/local-cli/templates/HelloWorld/_babelrc b/local-cli/templates/HelloWorld/_babelrc index a9ce1369e617e9..d4b74b5be7b43d 100644 --- a/local-cli/templates/HelloWorld/_babelrc +++ b/local-cli/templates/HelloWorld/_babelrc @@ -1,3 +1,3 @@ { - "presets": ["react-native"] + "presets": ["module:metro-react-native-babel-preset"] } From e05ceb824ca95609ddb19537191ec6a3729d49f9 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Mon, 13 Aug 2018 11:14:35 -0700 Subject: [PATCH 043/273] Add flow suppressions to xplat android Summary: .android.js files may be checked (when the next version of flow is released) by using `flow start --flowconfig-name .flowconfig.android` and `flow status --flowconfig-name .flowconfig.android` This diff adds suppressions to the errors that are in .android.js files, which flow does not check right now. When site is `react_native_fb` or `react_native_android_fb`, error will be suppressed when checking with .flowconfig.android When site is `react_native_fb` or `react_native_ios_fb`, error will be suppressed when checking with .flowconfig. You can use `react_native_fb` when it should be suppressed for both. The controller you requested could not be found. Reviewed By: TheSavior Differential Revision: D9122178 fbshipit-source-id: 0ec9d3cae3d887f58645e6585b2a3f6c3889b13e --- .../AccessibilityInfo.android.js | 2 + .../ActivityIndicator/ActivityIndicator.js | 2 + .../Components/CheckBox/CheckBox.android.js | 4 ++ .../Picker/PickerAndroid.android.js | 22 +++++++++++ .../StatusBar/StatusBarIOS.android.js | 2 + .../ViewPager/ViewPagerAndroid.android.js | 10 +++++ Libraries/Image/Image.android.js | 6 +++ Libraries/Network/XMLHttpRequest.js | 2 + .../js/ProgressBarAndroidExample.android.js | 4 ++ RNTester/js/RNTesterApp.android.js | 30 +++++++++++++++ RNTester/js/RNTesterExampleList.js | 2 + RNTester/js/RNTesterList.android.js | 16 ++++++++ RNTester/js/TextInputExample.android.js | 38 +++++++++++++++++++ 13 files changed, 140 insertions(+) diff --git a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js index 09547ea06367b2..f3bb359b70e37d 100644 --- a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js +++ b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js @@ -35,6 +35,8 @@ const _subscriptions = new Map(); */ const AccessibilityInfo = { + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ fetch: function(): Promise { return new Promise((resolve, reject) => { RCTAccessibilityInfo.isTouchExplorationEnabled(function(resp) { diff --git a/Libraries/Components/ActivityIndicator/ActivityIndicator.js b/Libraries/Components/ActivityIndicator/ActivityIndicator.js index abe6a75af9478e..1969b59d4edcb8 100644 --- a/Libraries/Components/ActivityIndicator/ActivityIndicator.js +++ b/Libraries/Components/ActivityIndicator/ActivityIndicator.js @@ -103,6 +103,8 @@ const ActivityIndicator = ( styles.container, style, )}> + {/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */} ); diff --git a/Libraries/Components/CheckBox/CheckBox.android.js b/Libraries/Components/CheckBox/CheckBox.android.js index 0c7f13decd8c13..45a3e6f08ac0c4 100644 --- a/Libraries/Components/CheckBox/CheckBox.android.js +++ b/Libraries/Components/CheckBox/CheckBox.android.js @@ -131,7 +131,11 @@ let CheckBox = createReactClass({ let props = {...this.props}; props.onStartShouldSetResponder = () => true; props.onResponderTerminationRequest = () => false; + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ props.enabled = !this.props.disabled; + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ props.on = this.props.value; props.style = [styles.rctCheckBox, this.props.style]; diff --git a/Libraries/Components/Picker/PickerAndroid.android.js b/Libraries/Components/Picker/PickerAndroid.android.js index 1f80aa3928d05c..7066b942ad222c 100644 --- a/Libraries/Components/Picker/PickerAndroid.android.js +++ b/Libraries/Components/Picker/PickerAndroid.android.js @@ -49,6 +49,8 @@ class PickerAndroid extends React.Component< }, *, > { + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ static propTypes = { ...ViewPropTypes, style: pickerStyleType, @@ -60,6 +62,8 @@ class PickerAndroid extends React.Component< testID: ReactPropTypes.string, }; + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ constructor(props, context) { super(props, context); const state = this._stateFromProps(props); @@ -70,6 +74,8 @@ class PickerAndroid extends React.Component< }; } + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ UNSAFE_componentWillReceiveProps(nextProps) { this.setState(this._stateFromProps(nextProps)); } @@ -86,6 +92,8 @@ class PickerAndroid extends React.Component< label: child.props.label, }; if (child.props.color) { + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */ childProps.color = processColor(child.props.color); } return childProps; @@ -106,6 +114,8 @@ class PickerAndroid extends React.Component< selected: this.state.initialSelectedIndex, testID: this.props.testID, style: [styles.pickerAndroid, this.props.style], + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ accessibilityLabel: this.props.accessibilityLabel, }; @@ -116,18 +126,26 @@ class PickerAndroid extends React.Component< if (this.props.onValueChange) { const position = event.nativeEvent.position; if (position >= 0) { + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */ const children = React.Children.toArray(this.props.children); const value = children[position].props.value; + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */ this.props.onValueChange(value, position); } else { this.props.onValueChange(null, position); } } + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ this._lastNativePosition = event.nativeEvent.position; this.forceUpdate(); }; componentDidMount() { + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ this._lastNativePosition = this.state.initialSelectedIndex; } @@ -140,11 +158,15 @@ class PickerAndroid extends React.Component< // truth, not the native component. if ( this.refs[REF_PICKER] && + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ this.state.selectedIndex !== this._lastNativePosition ) { this.refs[REF_PICKER].setNativeProps({ selected: this.state.selectedIndex, }); + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ this._lastNativePosition = this.state.selectedIndex; } } diff --git a/Libraries/Components/StatusBar/StatusBarIOS.android.js b/Libraries/Components/StatusBar/StatusBarIOS.android.js index 96f77d7868fbff..78831fab6d17e7 100644 --- a/Libraries/Components/StatusBar/StatusBarIOS.android.js +++ b/Libraries/Components/StatusBar/StatusBarIOS.android.js @@ -12,4 +12,6 @@ const NativeEventEmitter = require('NativeEventEmitter'); +/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found when + * making Flow check .android.js files. */ module.exports = new NativeEventEmitter('StatusBarManager'); diff --git a/Libraries/Components/ViewPager/ViewPagerAndroid.android.js b/Libraries/Components/ViewPager/ViewPagerAndroid.android.js index 2ccdd31b56365d..2b69a2777a3ae6 100644 --- a/Libraries/Components/ViewPager/ViewPagerAndroid.android.js +++ b/Libraries/Components/ViewPager/ViewPagerAndroid.android.js @@ -82,6 +82,8 @@ class ViewPagerAndroid extends React.Component<{ keyboardDismissMode?: 'none' | 'on-drag', scrollEnabled?: boolean, }> { + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ static propTypes = { ...ViewPropTypes, /** @@ -154,14 +156,20 @@ class ViewPagerAndroid extends React.Component<{ } } + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ getInnerViewNode = (): ReactComponent => { return this.refs[VIEWPAGER_REF].getInnerViewNode(); }; + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ _childrenWithOverridenStyle = (): Array => { // Override styles so that each page will fill the parent. Native component // will handle positioning of elements, so it's not important to offset // them correctly. + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ return React.Children.map(this.props.children, function(child) { if (!child) { return null; @@ -247,6 +255,8 @@ class ViewPagerAndroid extends React.Component<{ =0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */ style={this.props.style} onPageScroll={this._onPageScroll} onPageScrollStateChanged={this._onPageScrollStateChanged} diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index c8cedddabb2a37..0058b210d957bd 100644 --- a/Libraries/Image/Image.android.js +++ b/Libraries/Image/Image.android.js @@ -219,8 +219,12 @@ let Image = ( let style; let sources; if (source?.uri != null) { + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ const {width, height} = source; style = flattenStyle([{width, height}, styles.base, props.style]); + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ sources = [{uri: source.uri}]; } else { style = flattenStyle([styles.base, props.style]); @@ -232,6 +236,8 @@ let Image = ( style, shouldNotifyLoadEvents: !!(onLoadStart || onLoad || onLoadEnd || onError), src: sources, + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ headers: source?.headers, defaultSrc: defaultSource ? defaultSource.uri : null, loadingIndicatorSrc: loadingIndicatorSource diff --git a/Libraries/Network/XMLHttpRequest.js b/Libraries/Network/XMLHttpRequest.js index e8be40a0ac6540..273b0714481d07 100644 --- a/Libraries/Network/XMLHttpRequest.js +++ b/Libraries/Network/XMLHttpRequest.js @@ -522,6 +522,8 @@ class XMLHttpRequest extends EventTarget(...XHR_EVENTS) { this._url, this._headers, data, + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ nativeResponseType, incrementalEvents, this.timeout, diff --git a/RNTester/js/ProgressBarAndroidExample.android.js b/RNTester/js/ProgressBarAndroidExample.android.js index 2b3d7feeafcc88..17da936b26196e 100644 --- a/RNTester/js/ProgressBarAndroidExample.android.js +++ b/RNTester/js/ProgressBarAndroidExample.android.js @@ -48,6 +48,8 @@ class ProgressBarAndroidExample extends React.Component<{}> { return ( + {/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */} @@ -56,6 +58,8 @@ class ProgressBarAndroidExample extends React.Component<{}> { + {/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */} diff --git a/RNTester/js/RNTesterApp.android.js b/RNTester/js/RNTesterApp.android.js index 42c43b81aa8ca1..61f2260294a704 100644 --- a/RNTester/js/RNTesterApp.android.js +++ b/RNTester/js/RNTesterApp.android.js @@ -23,6 +23,8 @@ const ToolbarAndroid = require('ToolbarAndroid'); const RNTesterActions = require('./RNTesterActions'); const RNTesterExampleContainer = require('./RNTesterExampleContainer'); const RNTesterExampleList = require('./RNTesterExampleList'); +/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found when + * making Flow check .android.js files. */ const RNTesterList = require('./RNTesterList'); const RNTesterNavigationReducer = require('./RNTesterNavigationReducer'); const UIManager = require('UIManager'); @@ -96,12 +98,18 @@ class RNTesterApp extends React.Component { drawerWidth={Dimensions.get('window').width - DRAWER_WIDTH_LEFT} keyboardDismissMode="on-drag" onDrawerOpen={() => { + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */ this._overrideBackPressForDrawerLayout = true; }} onDrawerClose={() => { + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */ this._overrideBackPressForDrawerLayout = false; }} ref={drawer => { + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */ this.drawer = drawer; }} renderNavigationView={this._renderDrawerContent} @@ -114,6 +122,8 @@ class RNTesterApp extends React.Component { _renderDrawerContent = () => { return ( + {/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */} { this._handleAction(RNTesterActions.Back()); }} ref={example => { + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue + * was found when making Flow check .android.js files. */ this._exampleRef = example; }} /> @@ -146,6 +158,8 @@ class RNTesterApp extends React.Component { =0.78.0 site=react_native_android_fb) This issue + * was found when making Flow check .android.js files. */ onIconClicked={() => this.drawer.openDrawer()} style={styles.toolbar} title={ExampleModule.title} @@ -153,6 +167,8 @@ class RNTesterApp extends React.Component { { + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue + * was found when making Flow check .android.js files. */ this._exampleRef = example; }} /> @@ -166,10 +182,14 @@ class RNTesterApp extends React.Component { =0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */ onIconClicked={() => this.drawer.openDrawer()} style={styles.toolbar} title="RNTester" /> + {/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */} { } _handleAction = (action: Object): boolean => { + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ this.drawer && this.drawer.closeDrawer(); const newState = RNTesterNavigationReducer(this.state, action); if (this.state !== newState) { @@ -191,16 +213,24 @@ class RNTesterApp extends React.Component { }; _handleBackButtonPress = () => { + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ if (this._overrideBackPressForDrawerLayout) { // This hack is necessary because drawer layout provides an imperative API // with open and close methods. This code would be cleaner if the drawer // layout provided an `isOpen` prop and allowed us to pass a `onDrawerClose` handler. + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ this.drawer && this.drawer.closeDrawer(); return true; } if ( + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ this._exampleRef && this._exampleRef.handleBackAction && + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ this._exampleRef.handleBackAction() ) { return true; diff --git a/RNTester/js/RNTesterExampleList.js b/RNTester/js/RNTesterExampleList.js index 325a5bce88a50c..7ad207a8091c71 100644 --- a/RNTester/js/RNTesterExampleList.js +++ b/RNTester/js/RNTesterExampleList.js @@ -21,6 +21,8 @@ const RNTesterActions = require('./RNTesterActions'); const RNTesterStatePersister = require('./RNTesterStatePersister'); const View = require('View'); +/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found when + * making Flow check .android.js files. */ import type {RNTesterExample} from './RNTesterList.ios'; import type {PassProps} from './RNTesterStatePersister'; import type {DangerouslyImpreciseStyleProp} from 'StyleSheet'; diff --git a/RNTester/js/RNTesterList.android.js b/RNTester/js/RNTesterList.android.js index 8e8f6b791b8f4c..82906abc046a47 100644 --- a/RNTester/js/RNTesterList.android.js +++ b/RNTester/js/RNTesterList.android.js @@ -62,6 +62,8 @@ const ComponentExamples: Array = [ }, { key: 'ProgressBarAndroidExample', + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ module: require('./ProgressBarAndroidExample'), }, { @@ -98,14 +100,20 @@ const ComponentExamples: Array = [ }, { key: 'TextExample', + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ module: require('./TextExample'), }, { key: 'TextInputExample', + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ module: require('./TextInputExample'), }, { key: 'ToolbarAndroidExample', + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ module: require('./ToolbarAndroidExample'), }, { @@ -118,6 +126,8 @@ const ComponentExamples: Array = [ }, { key: 'ViewPagerAndroidExample', + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ module: require('./ViewPagerAndroidExample'), }, { @@ -129,6 +139,8 @@ const ComponentExamples: Array = [ const APIExamples: Array = [ { key: 'AccessibilityAndroidExample', + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ module: require('./AccessibilityAndroidExample'), }, { @@ -205,6 +217,8 @@ const APIExamples: Array = [ }, { key: 'PermissionsExampleAndroid', + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ module: require('./PermissionsExampleAndroid'), }, { @@ -229,6 +243,8 @@ const APIExamples: Array = [ }, { key: 'ToastAndroidExample', + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ module: require('./ToastAndroidExample'), }, { diff --git a/RNTester/js/TextInputExample.android.js b/RNTester/js/TextInputExample.android.js index 30cee2eb29aca4..5fba895bf2a551 100644 --- a/RNTester/js/TextInputExample.android.js +++ b/RNTester/js/TextInputExample.android.js @@ -84,6 +84,8 @@ class RewriteExample extends React.Component<$FlowFixMeProps, $FlowFixMeState> { var remainder = limit - this.state.text.length; var remainderColor = remainder > 5 ? 'blue' : 'red'; return ( + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ { text = text.replace(/ /g, '_'); this.setState({text}); }} + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */ style={styles.default} value={this.state.text} /> + {/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */} {remainder} @@ -299,6 +305,8 @@ class SelectionExample extends React.Component< onChangeText={value => this.setState({value})} onSelectionChange={this.onSelectionChange.bind(this)} ref={textInput => (this._textInput = textInput)} + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */ selection={this.state.selection} style={this.props.style} value={this.state.value} @@ -324,6 +332,8 @@ class AutogrowingTextInputExample extends React.Component<{}> { constructor(props) { super(props); + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ this.state = { width: 100, multiline: true, @@ -336,12 +346,18 @@ class AutogrowingTextInputExample extends React.Component<{}> { } UNSAFE_componentWillReceiveProps(props) { + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ this.setState({ + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ multiline: props.multiline, }); } render() { + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found + * when making Flow check .android.js files. */ var {style, multiline, ...props} = this.props; return ( @@ -351,25 +367,43 @@ class AutogrowingTextInputExample extends React.Component<{}> { minimumValue={0} maximumValue={100} step={10} + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */ onValueChange={value => this.setState({width: value})} /> Multiline: =0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */ value={this.state.multiline} + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */ onValueChange={value => this.setState({multiline: value})} /> TextInput: =0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */ multiline={this.state.multiline} + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */ style={[style, {width: this.state.width + '%'}]} + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */ onChangeText={value => this.setState({text: value})} onContentSizeChange={event => + /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */ this.setState({contentSize: event.nativeEvent.contentSize}) } {...props} /> Plain text value representation: + {/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */} {this.state.text} + {/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */} Content Size: {JSON.stringify(this.state.contentSize)} ); @@ -407,6 +441,8 @@ exports.examples = [ =0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */ style={styles.input} accessibilityLabel="I am the accessibility label for text input" /> @@ -801,6 +837,8 @@ exports.examples = [ return ( =0.78.0 site=react_native_android_fb) This issue was + * found when making Flow check .android.js files. */ style={styles.default} value="text selection can be changed" /> From 555c6c68f8651d53de84f213b65d8f5d8193ef47 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Mon, 13 Aug 2018 11:17:19 -0700 Subject: [PATCH 044/273] Add test to sync RN github flow configs Summary: Adds three more tests: * compare RN github ios and android flowconfigs * compare xplat/js ios flowconfig with RN github ios flowconfig * compare xplat/js android flowconfig with RN github android flowconfig Reviewed By: TheSavior Differential Revision: D9191176 fbshipit-source-id: 34f3644ffc5a26d3bdfd94b6c05a138407aaedeb --- .github.flowconfig.android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github.flowconfig.android b/.github.flowconfig.android index 83d6e2225713a9..e3741c8d4c8fa7 100644 --- a/.github.flowconfig.android +++ b/.github.flowconfig.android @@ -51,8 +51,8 @@ module.system.haste.name_reducers='^.*/\([a-zA-Z0-9$_.-]+\.js\(\.flow\)?\)$' -> # strip .js or .js.flow suffix module.system.haste.name_reducers='^\(.*\)\.js\(\.flow\)?$' -> '\1' # strip .android suffix -module.system.haste.name_reducers='^\(.*\)\.ios$' -> '\1' module.system.haste.name_reducers='^\(.*\)\.android$' -> '\1' +module.system.haste.name_reducers='^\(.*\)\.ios$' -> '\1' module.system.haste.name_reducers='^\(.*\)\.native$' -> '\1' module.system.haste.paths.blacklist=.*/__tests__/.* module.system.haste.paths.blacklist=.*/__mocks__/.* From 7b0774811e6d7d5a5d93f5be55f5daf05f4ddfdc Mon Sep 17 00:00:00 2001 From: Mehdi Mulani Date: Mon, 13 Aug 2018 11:26:15 -0700 Subject: [PATCH 045/273] Correctly find rootView when RCTTouchHandler is in a RCTSurface Summary: @public I'm surprised this hasn't caused an issue earlier. RCTTouchHandler is hooked up to RCTSurfaceView which itself contains a rootView. Thus when this calculation happens, a root view is never found. We can't assign to the root view since it created and destroyed frequently, so it makes the most sense to look for the RCTSurfaceView here and treat it as a root view. Reviewed By: fkgozali Differential Revision: D9296840 fbshipit-source-id: ba5320583201f9d5c0176847cc6e6087b6a6459b --- React/Base/RCTTouchHandler.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/React/Base/RCTTouchHandler.m b/React/Base/RCTTouchHandler.m index 5447a9a8a9f7ea..66ee73d93c6d2f 100644 --- a/React/Base/RCTTouchHandler.m +++ b/React/Base/RCTTouchHandler.m @@ -13,6 +13,7 @@ #import "RCTBridge.h" #import "RCTEventDispatcher.h" #import "RCTLog.h" +#import "RCTSurfaceView.h" #import "RCTTouchEvent.h" #import "RCTUIManager.h" #import "RCTUtils.h" @@ -246,7 +247,7 @@ - (void)_updateAndDispatchTouches:(NSSet *)touches - (void)_cacheRootView { UIView *rootView = self.view; - while (rootView.superview && ![rootView isReactRootView]) { + while (rootView.superview && ![rootView isReactRootView] && ![rootView isKindOfClass:[RCTSurfaceView class]]) { rootView = rootView.superview; } _cachedRootView = rootView; From 49150aa3d0d947abfe7a5066ce19468704a5e669 Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Mon, 13 Aug 2018 11:47:23 -0700 Subject: [PATCH 046/273] RN: Polyfill `String#padEnd` and `String#padStart` Summary: Adds polyfills for `String.prototype.padEnd` and `String.prototype.padStart`. Reviewed By: mjesun Differential Revision: D9233437 fbshipit-source-id: 3430450f28b4cec8f1c74af5f169e9bdef044ae8 --- Libraries/polyfills/String.prototype.es6.js | 34 +++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/Libraries/polyfills/String.prototype.es6.js b/Libraries/polyfills/String.prototype.es6.js index ac46fc873d2689..65551380322441 100644 --- a/Libraries/polyfills/String.prototype.es6.js +++ b/Libraries/polyfills/String.prototype.es6.js @@ -124,3 +124,37 @@ if (!String.prototype.codePointAt) { return first; }; } + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd +if (!String.prototype.padEnd) { + String.prototype.padEnd = function padEnd(targetLength, padString) { + targetLength = targetLength >> 0; //floor if number or convert non-number to 0; + padString = String(typeof padString !== 'undefined' ? padString : ' '); + if (this.length > targetLength) { + return String(this); + } else { + targetLength = targetLength - this.length; + if (targetLength > padString.length) { + padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed + } + return String(this) + padString.slice(0, targetLength); + } + }; +} + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart +if (!String.prototype.padStart) { + String.prototype.padStart = function padStart(targetLength, padString) { + targetLength = targetLength >> 0; //truncate if number or convert non-number to 0; + padString = String(typeof padString !== 'undefined' ? padString : ' '); + if (this.length > targetLength) { + return String(this); + } else { + targetLength = targetLength - this.length; + if (targetLength > padString.length) { + padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed + } + return padString.slice(0, targetLength) + String(this); + } + }; +} From c66315e367568507f4aa6de99cdadff34e5e77d8 Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Mon, 13 Aug 2018 11:47:35 -0700 Subject: [PATCH 047/273] RN: Fix Touchable Debug View Summary: Fixes the `Touchable` debug view. The `child.type` is no longer a subclass of `React.Component` and no longer has `displayName`. It should be fine to have a hard dependency on `Text` and `View`, because... what app does not use them? Reviewed By: TheSavior Differential Revision: D9232036 fbshipit-source-id: 06f4091bf8e21cada3af50def2fdd41a6ad84f79 --- .../TouchableNativeFeedback.android.js | 3 ++- .../Touchable/TouchableWithoutFeedback.js | 20 ++----------------- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/Libraries/Components/Touchable/TouchableNativeFeedback.android.js b/Libraries/Components/Touchable/TouchableNativeFeedback.android.js index db99fbde111bad..292d9356af2c1f 100644 --- a/Libraries/Components/Touchable/TouchableNativeFeedback.android.js +++ b/Libraries/Components/Touchable/TouchableNativeFeedback.android.js @@ -16,6 +16,7 @@ const ReactNative = require('ReactNative'); const Touchable = require('Touchable'); const TouchableWithoutFeedback = require('TouchableWithoutFeedback'); const UIManager = require('UIManager'); +const View = require('View'); const createReactClass = require('create-react-class'); const ensurePositiveDelayProps = require('ensurePositiveDelayProps'); @@ -238,7 +239,7 @@ const TouchableNativeFeedback = createReactClass({ render: function() { const child = React.Children.only(this.props.children); let children = child.props.children; - if (Touchable.TOUCH_TARGET_DEBUG && child.type.displayName === 'View') { + if (Touchable.TOUCH_TARGET_DEBUG && child.type === View) { if (!Array.isArray(children)) { children = [children]; } diff --git a/Libraries/Components/Touchable/TouchableWithoutFeedback.js b/Libraries/Components/Touchable/TouchableWithoutFeedback.js index 06af8ab40a1b7e..3bb69617ecc539 100755 --- a/Libraries/Components/Touchable/TouchableWithoutFeedback.js +++ b/Libraries/Components/Touchable/TouchableWithoutFeedback.js @@ -15,6 +15,7 @@ const React = require('React'); const PropTypes = require('prop-types'); const TimerMixin = require('react-timer-mixin'); const Touchable = require('Touchable'); +const View = require('View'); const createReactClass = require('create-react-class'); const ensurePositiveDelayProps = require('ensurePositiveDelayProps'); @@ -225,28 +226,12 @@ const TouchableWithoutFeedback = ((createReactClass({ // $FlowFixMe(>=0.41.0) const child = React.Children.only(this.props.children); let children = child.props.children; - warning( - !child.type || child.type.displayName !== 'Text', - 'TouchableWithoutFeedback does not work well with Text children. Wrap children in a View instead. See ' + - ((child._owner && child._owner.getName && child._owner.getName()) || - ''), - ); - if ( - Touchable.TOUCH_TARGET_DEBUG && - child.type && - child.type.displayName === 'View' - ) { + if (Touchable.TOUCH_TARGET_DEBUG && child.type === View) { children = React.Children.toArray(children); children.push( Touchable.renderDebugView({color: 'red', hitSlop: this.props.hitSlop}), ); } - const style = - Touchable.TOUCH_TARGET_DEBUG && - child.type && - child.type.displayName === 'Text' - ? [child.props.style, {color: 'red'}] - : child.props.style; return (React: any).cloneElement(child, { accessible: this.props.accessible !== false, accessibilityLabel: this.props.accessibilityLabel, @@ -266,7 +251,6 @@ const TouchableWithoutFeedback = ((createReactClass({ onResponderMove: this.touchableHandleResponderMove, onResponderRelease: this.touchableHandleResponderRelease, onResponderTerminate: this.touchableHandleResponderTerminate, - style, children, }); }, From 4152e70b47aa7c5d424d559862939a531b85b6d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Mon, 13 Aug 2018 11:59:59 -0700 Subject: [PATCH 048/273] Add missing trailing comma Summary: Adds missing comma, following up on https://github.com/facebook/react-native/pull/20178. Thanks to LinusU for pointing out the error. Reviewed By: TheSavior Differential Revision: D9242887 fbshipit-source-id: 4b547396722d0e37dc5c8eb3439b9a441c3c0ac2 --- jest/preprocessor.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/jest/preprocessor.js b/jest/preprocessor.js index 6c71b795ed6dc5..17838def4c2e86 100644 --- a/jest/preprocessor.js +++ b/jest/preprocessor.js @@ -39,15 +39,12 @@ module.exports = { process(src /*: string */, file /*: string */) { if (nodeFiles.test(file)) { // node specific transforms only - return babelTransformSync( - src, - { - filename: file, - sourceType: 'script', - ...nodeOptions, - ast: false - }, - ).code; + return babelTransformSync(src, { + filename: file, + sourceType: 'script', + ...nodeOptions, + ast: false, + }).code; } const {ast} = transformer.transform({ From 074845106d88f9214140d83ce0e2b070cec9cfdd Mon Sep 17 00:00:00 2001 From: Mike Grabowski Date: Tue, 14 Aug 2018 13:07:16 +0200 Subject: [PATCH 049/273] [0.57.0-rc.0] Bump version numbers --- Libraries/Core/ReactNativeVersion.js | 8 ++++---- React/Base/RCTVersion.m | 4 ++-- ReactAndroid/gradle.properties | 2 +- .../react/modules/systeminfo/ReactNativeVersion.java | 4 ++-- package.json | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Libraries/Core/ReactNativeVersion.js b/Libraries/Core/ReactNativeVersion.js index 320b26ac84db6b..3c3a2232cbea18 100644 --- a/Libraries/Core/ReactNativeVersion.js +++ b/Libraries/Core/ReactNativeVersion.js @@ -1,17 +1,17 @@ /** + * @generated by scripts/bump-oss-version.js + * * Copyright (c) 2015-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @format - * @generated by scripts/bump-oss-version.js * @flow */ exports.version = { major: 0, - minor: 0, + minor: 57, patch: 0, - prerelease: null, + prerelease: 'rc.0', }; diff --git a/React/Base/RCTVersion.m b/React/Base/RCTVersion.m index 41f178395c9018..6934e6619d9cb6 100644 --- a/React/Base/RCTVersion.m +++ b/React/Base/RCTVersion.m @@ -21,9 +21,9 @@ static void __makeVersion() { __rnVersion = @{ RCTVersionMajor: @(0), - RCTVersionMinor: @(0), + RCTVersionMinor: @(57), RCTVersionPatch: @(0), - RCTVersionPrerelease: [NSNull null], + RCTVersionPrerelease: @"rc.0", }; } diff --git a/ReactAndroid/gradle.properties b/ReactAndroid/gradle.properties index 35b82ce516f757..a42263b074e880 100644 --- a/ReactAndroid/gradle.properties +++ b/ReactAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=1000.0.0-master +VERSION_NAME=0.57.0-rc.0 GROUP=com.facebook.react POM_NAME=ReactNative diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java index 9e8ac43662b364..7441b9e17cd2db 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java @@ -16,7 +16,7 @@ public class ReactNativeVersion { public static final Map VERSION = MapBuilder.of( "major", 0, - "minor", 0, + "minor", 57, "patch", 0, - "prerelease", null); + "prerelease", "rc.0"); } diff --git a/package.json b/package.json index 10d2de07dbed69..98141199c7b7a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native", - "version": "1000.0.0", + "version": "0.57.0-rc.0", "description": "A framework for building native apps using React", "license": "MIT", "repository": { @@ -237,4 +237,4 @@ } } } -} +} \ No newline at end of file From 5288656c476c3e2175d37ee33a77ba408a8c372f Mon Sep 17 00:00:00 2001 From: Ives van Hoorne Date: Thu, 16 Aug 2018 08:32:09 -0700 Subject: [PATCH 050/273] Bump metro to 0.43.6 Summary: New version of metro to add module.id Reviewed By: rafeca Differential Revision: D9360070 fbshipit-source-id: fc0e2d98483404ddbc1ca920c4f42f52573734c6 --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 98141199c7b7a6..7bd2c8422e5902 100644 --- a/package.json +++ b/package.json @@ -169,10 +169,10 @@ "graceful-fs": "^4.1.3", "inquirer": "^3.0.6", "lodash": "^4.17.5", - "metro": "^0.43.5", - "metro-babel-register": "^0.43.5", - "metro-core": "^0.43.5", - "metro-memory-fs": "^0.43.5", + "metro": "^0.43.6", + "metro-babel-register": "^0.43.6", + "metro-core": "^0.43.6", + "metro-memory-fs": "^0.43.6", "mime": "^1.3.4", "minimist": "^1.2.0", "mkdirp": "^0.5.1", From 3afe7115958927233bed7098c2b1ef522435990c Mon Sep 17 00:00:00 2001 From: Eric Rozell Date: Sat, 18 Aug 2018 05:18:44 -0700 Subject: [PATCH 051/273] Do not override `metro.config.js` settings (#20705) Summary: React Native overrides the `metro.config.js` settings for, e.g., `hasteImplModulePath`, which prevents us from adding a `metro.config.js` file to the repo for `react-native-windows` to allow us to resolve Haste modules at the top-level of the repo. This change ensures that if a user has a `metro.config.js` file, those settings are not overwritten by React Native. Pull Request resolved: https://github.com/facebook/react-native/pull/20705 Differential Revision: D9390146 Pulled By: hramos fbshipit-source-id: 5ccc137490410ace72d7b0e68f2bafcbb233c59f --- local-cli/core/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/local-cli/core/index.js b/local-cli/core/index.js index 1a9ab03db36031..7027706250a4c1 100644 --- a/local-cli/core/index.js +++ b/local-cli/core/index.js @@ -132,9 +132,9 @@ async function getCliConfig(): Promise { ); config.transformer.assetRegistryPath = ASSET_REGISTRY_PATH; - config.resolver.hasteImplModulePath = defaultConfig.hasteImplModulePath; - config.resolver.platforms = defaultConfig.getPlatforms(); - config.resolver.providesModuleNodeModules = defaultConfig.getProvidesModuleNodeModules(); + config.resolver.hasteImplModulePath = config.resolver.hasteImplModulePath || defaultConfig.hasteImplModulePath; + config.resolver.platforms = config.resolver.platforms || defaultConfig.getPlatforms(); + config.resolver.providesModuleNodeModules = config.resolver.providesModuleNodeModules || defaultConfig.getProvidesModuleNodeModules(); return {...defaultRNConfig, ...config}; } From b948dd9516ba88b5d2b94a1aea91f6361f6a6a21 Mon Sep 17 00:00:00 2001 From: gengjiawen Date: Mon, 20 Aug 2018 07:19:59 -0700 Subject: [PATCH 052/273] Fixes #20712 on unix-like OS (#20751) Summary: add `packager.sh` for run-android task for unix like system. This only fix on linux and macOS. pass all current ci. none [GENERAL] [BUGFIX] [CLI] - add `packager.sh` back for run-android task Pull Request resolved: https://github.com/facebook/react-native/pull/20751 Differential Revision: D9398197 Pulled By: hramos fbshipit-source-id: 213b066c0c034136c5ad5bbf8d45c6f331b1d185 --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 7bd2c8422e5902..19f07c6ce10125 100644 --- a/package.json +++ b/package.json @@ -103,6 +103,7 @@ "scripts/ios-install-third-party.sh", "scripts/launchPackager.bat", "scripts/launchPackager.command", + "scripts/packager.sh", "scripts/react-native-xcode.sh", "jest-preset.json", "jest", From e90d9ca70bbcef24744db8bae04bad5c6423d50d Mon Sep 17 00:00:00 2001 From: Eric Rozell Date: Mon, 20 Aug 2018 09:56:53 -0700 Subject: [PATCH 053/273] Apply `--reset-cache` argument to `bundle` command (#20706) Summary: The `--reset-cache` argument was not working correctly with the `bundle` command. This ensures the `--reset-cache` arg is passed to metro. Fixes #20703 Thank you for sending the PR! We appreciate you spending the time to work on these changes. Help us understand your motivation by explaining why you decided to make this change. If this PR fixes an issue, type "Fixes #issueNumber" to automatically close the issue when the PR is merged. Pull Request resolved: https://github.com/facebook/react-native/pull/20706 Differential Revision: D9400548 Pulled By: hramos fbshipit-source-id: 2c7ed0226cfcdffa8cc77506500c314552baef3f --- local-cli/bundle/buildBundle.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local-cli/bundle/buildBundle.js b/local-cli/bundle/buildBundle.js index bcb496cad05d21..cd31e21e0ded4d 100644 --- a/local-cli/bundle/buildBundle.js +++ b/local-cli/bundle/buildBundle.js @@ -56,7 +56,7 @@ async function buildBundle( platform: args.platform, }; - const server = new Server(config); + const server = new Server({...config, resetCache: args.resetCache}); try { const bundle = await output.build(server, requestOpts); From 9b3a6ec84b2956ae3e567adb54f4da429421f415 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 16 Aug 2018 13:33:53 -0700 Subject: [PATCH 054/273] Implement WKWebView to replace WebView Summary: @public `UIWebView` has been deprecated and replaced by `WKWebView`. This diff introduces a new component `WKWebView` that simply renders a `WKWebView` on iOS. This is the first in the stack of many diffs that'll be required to fully replace `UIWebView` with `WKWebView` in the `` React Native component. Eventually, I hope to introduce a prop called `useWebKitImplementation`, which, when true, will force RN to use `WKWebView` instead of `UIWebView` for the `` component. The only thing that's been implemented so far is the `source` property. Reviewed By: mmmulani Differential Revision: D6266100 fbshipit-source-id: 65862e34bd98db7fff0349cf26888afee43a56e4 --- .../Components/WKWebView/WKWebView.android.js | 22 ++++++ .../Components/WKWebView/WKWebView.ios.js | 14 ++++ React/Views/RCTWKWebView.h | 22 ++++++ React/Views/RCTWKWebView.m | 72 +++++++++++++++++++ React/Views/RCTWKWebViewManager.m | 18 +++++ 5 files changed, 148 insertions(+) create mode 100644 Libraries/Components/WKWebView/WKWebView.android.js create mode 100644 Libraries/Components/WKWebView/WKWebView.ios.js create mode 100644 React/Views/RCTWKWebView.h create mode 100644 React/Views/RCTWKWebView.m create mode 100644 React/Views/RCTWKWebViewManager.m diff --git a/Libraries/Components/WKWebView/WKWebView.android.js b/Libraries/Components/WKWebView/WKWebView.android.js new file mode 100644 index 00000000000000..a4cab312304c75 --- /dev/null +++ b/Libraries/Components/WKWebView/WKWebView.android.js @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow + * @providesModule WKWebView + */ + +const React = require('React'); +const View = require('View'); +const Text = require('Text'); + +module.exports = () => { + return ( + + Android version not implemented. + + ); +}; diff --git a/Libraries/Components/WKWebView/WKWebView.ios.js b/Libraries/Components/WKWebView/WKWebView.ios.js new file mode 100644 index 00000000000000..d1af14bfebd6e7 --- /dev/null +++ b/Libraries/Components/WKWebView/WKWebView.ios.js @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow + * @providesModule WKWebView + */ + +const requireNativeComponent = require('requireNativeComponent'); + +module.exports = requireNativeComponent('RCTWKWebView'); diff --git a/React/Views/RCTWKWebView.h b/React/Views/RCTWKWebView.h new file mode 100644 index 00000000000000..7e985f68e7af9c --- /dev/null +++ b/React/Views/RCTWKWebView.h @@ -0,0 +1,22 @@ +/** + * 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. + */ + +#import + +@class RCTWKWebView; + +@protocol RCTWKWebViewDelegate +@end + +@interface RCTWKWebView : RCTView + +@property (nonatomic, weak) id delegate; +@property (nonatomic, copy) NSDictionary *source; + +@end diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m new file mode 100644 index 00000000000000..98cdf290b87511 --- /dev/null +++ b/React/Views/RCTWKWebView.m @@ -0,0 +1,72 @@ +#import "RCTWKWebView.h" + +#import + +#import + +#import "RCTAutoInsetsProtocol.h" + +@interface RCTWKWebView () +@end + +@implementation RCTWKWebView +{ + WKWebView *_webView; +} + +- (void)dealloc +{ + +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + if ((self = [super initWithFrame:frame])) { + super.backgroundColor = [UIColor clearColor]; + _webView = [[WKWebView alloc] initWithFrame:self.bounds]; + _webView.UIDelegate = self; + [self addSubview:_webView]; + } + return self; +} + +- (void)setSource:(NSDictionary *)source +{ + if (![_source isEqualToDictionary:source]) { + _source = [source copy]; + + // Check for a static html source first + NSString *html = [RCTConvert NSString:source[@"html"]]; + if (html) { + NSURL *baseURL = [RCTConvert NSURL:source[@"baseUrl"]]; + if (!baseURL) { + baseURL = [NSURL URLWithString:@"about:blank"]; + } + [_webView loadHTMLString:html baseURL:baseURL]; + return; + } + + NSURLRequest *request = [RCTConvert NSURLRequest:source]; + // Because of the way React works, as pages redirect, we actually end up + // passing the redirect urls back here, so we ignore them if trying to load + // the same url. We'll expose a call to 'reload' to allow a user to load + // the existing page. + if ([request.URL isEqual:_webView.URL]) { + return; + } + if (!request.URL) { + // Clear the webview + [_webView loadHTMLString:@"" baseURL:nil]; + return; + } + [_webView loadRequest:request]; + } +} + +- (void)layoutSubviews +{ + [super layoutSubviews]; + _webView.frame = self.bounds; +} + +@end diff --git a/React/Views/RCTWKWebViewManager.m b/React/Views/RCTWKWebViewManager.m new file mode 100644 index 00000000000000..e16bbe723e5087 --- /dev/null +++ b/React/Views/RCTWKWebViewManager.m @@ -0,0 +1,18 @@ +#import "RCTViewManager.h" +#import "RCTWKWebView.h" + +@interface RCTWKWebViewManager : RCTViewManager +@end + +@implementation RCTWKWebViewManager + +RCT_EXPORT_MODULE() + +- (UIView *)view +{ + return [RCTWKWebView new]; +} + +RCT_EXPORT_VIEW_PROPERTY(source, NSDictionary) + +@end From f7f9d0139099a109b6b33cb057a5822c4a91505e Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 16 Aug 2018 13:33:55 -0700 Subject: [PATCH 055/273] Implement onLoading(Start|Finish|Error) and injectedJavaScript props Summary: @public This diff includes four very straightforward changes: 1. Whenever the WebView starts loading, the `onLoadingStart` hook should be executed. The event passed into this hook should be decorated with the `navigationType`. 1. Whenever the WebView errors out while loading, the `onLoadingError` hook should be executed. 1. Whenever the WebView finishes loading (without any errors), the `onLoadingFinish` hook should be executed. 1. The serialized JavaScript passed into the `injectedJavaScript` prop should be executed when the WebView finishes loading. After execution finishes, the `onLoadingFinish` prop should be called with the serialized completion value of this JavaScript. Reviewed By: shergin Differential Revision: D6293532 fbshipit-source-id: 21407c766f73413046823ae605afc21e85cf9db6 --- React/Views/RCTWKWebView.h | 1 + React/Views/RCTWKWebView.m | 123 +++++++++++++++++++++++++++++- React/Views/RCTWKWebViewManager.m | 4 + 3 files changed, 126 insertions(+), 2 deletions(-) diff --git a/React/Views/RCTWKWebView.h b/React/Views/RCTWKWebView.h index 7e985f68e7af9c..8f00bf507814d8 100644 --- a/React/Views/RCTWKWebView.h +++ b/React/Views/RCTWKWebView.h @@ -18,5 +18,6 @@ @property (nonatomic, weak) id delegate; @property (nonatomic, copy) NSDictionary *source; +@property (nonatomic, copy) NSString *injectedJavaScript; @end diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m index 98cdf290b87511..ec8ba37b519130 100644 --- a/React/Views/RCTWKWebView.m +++ b/React/Views/RCTWKWebView.m @@ -6,12 +6,15 @@ #import "RCTAutoInsetsProtocol.h" -@interface RCTWKWebView () +@interface RCTWKWebView () +@property (nonatomic, copy) RCTDirectEventBlock onLoadingStart; +@property (nonatomic, copy) RCTDirectEventBlock onLoadingFinish; +@property (nonatomic, copy) RCTDirectEventBlock onLoadingError; +@property (nonatomic, copy) WKWebView *webView; @end @implementation RCTWKWebView { - WKWebView *_webView; } - (void)dealloc @@ -25,6 +28,7 @@ - (instancetype)initWithFrame:(CGRect)frame super.backgroundColor = [UIColor clearColor]; _webView = [[WKWebView alloc] initWithFrame:self.bounds]; _webView.UIDelegate = self; + _webView.navigationDelegate = self; [self addSubview:_webView]; } return self; @@ -69,4 +73,119 @@ - (void)layoutSubviews _webView.frame = self.bounds; } +- (NSMutableDictionary *)baseEvent +{ + NSDictionary *event = @{ + @"url": _webView.URL.absoluteString ?: @"", + @"title": _webView.title, + @"loading" : @(_webView.loading), + @"canGoBack": @(_webView.canGoBack), + @"canGoForward" : @(_webView.canGoForward) + }; + return [[NSMutableDictionary alloc] initWithDictionary: event]; +} + +#pragma mark - WKNavigationDelegate methods + +/** + * Decides whether to allow or cancel a navigation. + * @see https://fburl.com/42r9fxob + */ +- (void) webView:(WKWebView *)webView + decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction + decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler +{ + static NSDictionary *navigationTypes; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + navigationTypes = @{ + @(WKNavigationTypeLinkActivated): @"click", + @(WKNavigationTypeFormSubmitted): @"formsubmit", + @(WKNavigationTypeBackForward): @"backforward", + @(WKNavigationTypeReload): @"reload", + @(WKNavigationTypeFormResubmitted): @"formresubmit", + @(WKNavigationTypeOther): @"other", + }; + }); + + WKNavigationType navigationType = navigationAction.navigationType; + NSURLRequest *request = navigationAction.request; + + if (_onLoadingStart) { + // We have this check to filter out iframe requests and whatnot + BOOL isTopFrame = [request.URL isEqual:request.mainDocumentURL]; + if (isTopFrame) { + NSMutableDictionary *event = [self baseEvent]; + [event addEntriesFromDictionary: @{ + @"url": (request.URL).absoluteString, + @"navigationType": navigationTypes[@(navigationType)] + }]; + _onLoadingStart(event); + } + } + + // Allow all navigation by default + decisionHandler(WKNavigationResponsePolicyAllow); +} + +/** + * Called when an error occurs while the web view is loading content. + * @see https://fburl.com/km6vqenw + */ +- (void) webView:(WKWebView *)webView + didFailProvisionalNavigation:(WKNavigation *)navigation + withError:(NSError *)error +{ + if (_onLoadingError) { + if ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled) { + // NSURLErrorCancelled is reported when a page has a redirect OR if you load + // a new URL in the WebView before the previous one came back. We can just + // ignore these since they aren't real errors. + // http://stackoverflow.com/questions/1024748/how-do-i-fix-nsurlerrordomain-error-999-in-iphone-3-0-os + return; + } + + NSMutableDictionary *event = [self baseEvent]; + [event addEntriesFromDictionary:@{ + @"didFailProvisionalNavigation": @YES, + @"domain": error.domain, + @"code": @(error.code), + @"description": error.localizedDescription, + }]; + _onLoadingError(event); + } +} + +- (void)evaluateJS:(NSString *)js + thenCall: (void (^)(NSString*)) callback +{ + [self.webView evaluateJavaScript: js completionHandler: ^(id result, NSError *error) { + if (error == nil) { + callback([NSString stringWithFormat:@"%@", result]); + } + }]; +} + + +/** + * Called when the navigation is complete. + * @see https://fburl.com/rtys6jlb + */ +- (void) webView:(WKWebView *)webView + didFinishNavigation:(WKNavigation *)navigation +{ + if (_injectedJavaScript) { + [self evaluateJS: _injectedJavaScript thenCall: ^(NSString *jsEvaluationValue) { + NSMutableDictionary *event = [self baseEvent]; + event[@"jsEvaluationValue"] = jsEvaluationValue; + if (self.onLoadingFinish) { + self.onLoadingFinish(event); + } + }]; + } else if (_onLoadingFinish) { + _onLoadingFinish([self baseEvent]); + } +} + @end diff --git a/React/Views/RCTWKWebViewManager.m b/React/Views/RCTWKWebViewManager.m index e16bbe723e5087..e01198c7bae5bd 100644 --- a/React/Views/RCTWKWebViewManager.m +++ b/React/Views/RCTWKWebViewManager.m @@ -14,5 +14,9 @@ - (UIView *)view } RCT_EXPORT_VIEW_PROPERTY(source, NSDictionary) +RCT_EXPORT_VIEW_PROPERTY(onLoadingStart, RCTDirectEventBlock) +RCT_EXPORT_VIEW_PROPERTY(onLoadingFinish, RCTDirectEventBlock) +RCT_EXPORT_VIEW_PROPERTY(onLoadingError, RCTDirectEventBlock) +RCT_EXPORT_VIEW_PROPERTY(injectedJavaScript, NSString) @end From 94560cac258156b6f9ba82c2f3bb7ff840ddde5f Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 16 Aug 2018 13:33:58 -0700 Subject: [PATCH 056/273] Implement message passing! Summary: @public This diff implements message passing between the `WKWebView` and React Native. As with ``, we can only send/receive strings. **Usage:** 1. Set `messagingEnabled` to `true`. 1. To send data from the web view to React Native, call `postMessage(data)` within the web view. This forces React Native to execute the `onMessage` prop on the `WKWebView` component. `onMessage` will be called with an event `e`, where `e.nativeEvent.data` will be the data you passed into `postMessage`. 1. To send data from React Native to the web view, call `UIManager.dispatchViewManagerCommand` to dispatch the `UIManager.RCTWKWebView.Commands.postMessage` command. Look at [[ https://fburl.com/u1wusf2f | this part of the existing `` ]] component for more details. After you make the call, React Native will dispatch a `'message'` event to the `document` object within the webview. You can listen to the event by doing `document.addEventListener('message', callback)`. Let the event dispatched be `e`. Then, `e.data` is the data you sent over from React Native. [[ P58627181 | This Playground.js ]] illustrates the usage. Reviewed By: shergin Differential Revision: D6304850 fbshipit-source-id: 29075ef753296e9fb5a9cddeb1ad0f4ff7e28650 --- React/Views/RCTWKWebView.h | 3 ++ React/Views/RCTWKWebView.m | 67 ++++++++++++++++++++++++++++--- React/Views/RCTWKWebViewManager.h | 6 +++ React/Views/RCTWKWebViewManager.m | 25 ++++++++++-- 4 files changed, 91 insertions(+), 10 deletions(-) create mode 100644 React/Views/RCTWKWebViewManager.h diff --git a/React/Views/RCTWKWebView.h b/React/Views/RCTWKWebView.h index 8f00bf507814d8..d094b72d4ddeeb 100644 --- a/React/Views/RCTWKWebView.h +++ b/React/Views/RCTWKWebView.h @@ -18,6 +18,9 @@ @property (nonatomic, weak) id delegate; @property (nonatomic, copy) NSDictionary *source; +@property (nonatomic, assign) BOOL messagingEnabled; @property (nonatomic, copy) NSString *injectedJavaScript; +- (void)postMessage:(NSString *)message; + @end diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m index ec8ba37b519130..2c9aef5e570ffd 100644 --- a/React/Views/RCTWKWebView.m +++ b/React/Views/RCTWKWebView.m @@ -1,15 +1,15 @@ #import "RCTWKWebView.h" - #import - #import - #import "RCTAutoInsetsProtocol.h" -@interface RCTWKWebView () +static NSString *const MessageHanderName = @"ReactNative"; + +@interface RCTWKWebView () @property (nonatomic, copy) RCTDirectEventBlock onLoadingStart; @property (nonatomic, copy) RCTDirectEventBlock onLoadingFinish; @property (nonatomic, copy) RCTDirectEventBlock onLoadingError; +@property (nonatomic, copy) RCTDirectEventBlock onMessage; @property (nonatomic, copy) WKWebView *webView; @end @@ -26,7 +26,11 @@ - (instancetype)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { super.backgroundColor = [UIColor clearColor]; - _webView = [[WKWebView alloc] initWithFrame:self.bounds]; + WKWebViewConfiguration *wkWebViewConfig = [WKWebViewConfiguration new]; + wkWebViewConfig.userContentController = [WKUserContentController new]; + [wkWebViewConfig.userContentController addScriptMessageHandler: self name: MessageHanderName]; + + _webView = [[WKWebView alloc] initWithFrame:self.bounds configuration: wkWebViewConfig]; _webView.UIDelegate = self; _webView.navigationDelegate = self; [self addSubview:_webView]; @@ -34,6 +38,20 @@ - (instancetype)initWithFrame:(CGRect)frame return self; } +/** + * This method is called whenever JavaScript running within the web view calls: + * - window.webkit.messageHandlers.[MessageHanderName].postMessage + */ +- (void)userContentController:(WKUserContentController *)userContentController + didReceiveScriptMessage:(WKScriptMessage *)message +{ + if (_onMessage != nil) { + NSMutableDictionary *event = [self baseEvent]; + [event addEntriesFromDictionary: @{@"data": message.body}]; + _onMessage(event); + } +} + - (void)setSource:(NSDictionary *)source { if (![_source isEqualToDictionary:source]) { @@ -67,9 +85,21 @@ - (void)setSource:(NSDictionary *)source } } +- (void)postMessage:(NSString *)message +{ + NSDictionary *eventInitDict = @{@"data": message}; + NSString *source = [NSString + stringWithFormat:@"document.dispatchEvent(new MessageEvent('message', %@));", + RCTJSONStringify(eventInitDict, NULL) + ]; + [self evaluateJS: source thenCall: nil]; +} + - (void)layoutSubviews { [super layoutSubviews]; + + // Ensure webview takes the position and dimensions of RCTWKWebView _webView.frame = self.bounds; } @@ -161,7 +191,7 @@ - (void)evaluateJS:(NSString *)js thenCall: (void (^)(NSString*)) callback { [self.webView evaluateJavaScript: js completionHandler: ^(id result, NSError *error) { - if (error == nil) { + if (error == nil && callback != nil) { callback([NSString stringWithFormat:@"%@", result]); } }]; @@ -175,6 +205,31 @@ - (void)evaluateJS:(NSString *)js - (void) webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { + if (_messagingEnabled) { + #if RCT_DEV + + // Implementation inspired by Lodash.isNative. + NSString *isPostMessageNative = @"String(String(window.postMessage) === String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage'))"; + [self evaluateJS: isPostMessageNative thenCall: ^(NSString *result) { + if (! [result isEqualToString:@"true"]) { + RCTLogError(@"Setting onMessage on a WebView overrides existing values of window.postMessage, but a previous value was defined"); + } + }]; + #endif + + NSString *source = [NSString stringWithFormat: + @"(function() {" + "window.originalPostMessage = window.postMessage;" + + "window.postMessage = function(data) {" + "window.webkit.messageHandlers.%@.postMessage(String(data));" + "};" + "})();", + MessageHanderName + ]; + [self evaluateJS: source thenCall: nil]; + } + if (_injectedJavaScript) { [self evaluateJS: _injectedJavaScript thenCall: ^(NSString *jsEvaluationValue) { NSMutableDictionary *event = [self baseEvent]; diff --git a/React/Views/RCTWKWebViewManager.h b/React/Views/RCTWKWebViewManager.h new file mode 100644 index 00000000000000..9099e8cf3faf26 --- /dev/null +++ b/React/Views/RCTWKWebViewManager.h @@ -0,0 +1,6 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#import + +@interface RCTWKWebViewManager : RCTViewManager +@end diff --git a/React/Views/RCTWKWebViewManager.m b/React/Views/RCTWKWebViewManager.m index e01198c7bae5bd..fb1db9cc3dc24f 100644 --- a/React/Views/RCTWKWebViewManager.m +++ b/React/Views/RCTWKWebViewManager.m @@ -1,8 +1,7 @@ -#import "RCTViewManager.h" -#import "RCTWKWebView.h" +#import "RCTWKWebViewManager.h" -@interface RCTWKWebViewManager : RCTViewManager -@end +#import "RCTUIManager.h" +#import "RCTWKWebView.h" @implementation RCTWKWebViewManager @@ -19,4 +18,22 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(onLoadingError, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(injectedJavaScript, NSString) +/** + * Expose methods to enable messaging the webview. + */ +RCT_EXPORT_VIEW_PROPERTY(messagingEnabled, BOOL) +RCT_EXPORT_VIEW_PROPERTY(onMessage, RCTDirectEventBlock) + +RCT_EXPORT_METHOD(postMessage:(nonnull NSNumber *)reactTag message:(NSString *)message) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + RCTWKWebView *view = viewRegistry[reactTag]; + if (![view isKindOfClass:[RCTWKWebView class]]) { + RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); + } else { + [view postMessage:message]; + } + }]; +} + @end From 06cce04c2e9a04b82b71a254300ec31608a1e430 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 16 Aug 2018 13:34:01 -0700 Subject: [PATCH 057/273] Implement 'bounces' prop Summary: @public The content that loads inside `WKWebView` renders within a `ScrollView`. Suppose the user pulls the page down when its top edge hits the top edge of the web view. Then, one of two things can happen as the user continues to pull the page down: 1. We let the page be pulled past the top edge of the web view. 1. We fix the page's vertical offset to 0 so that it doesn't move past the top edge of the web view. The property that controls this behaviour is ``. In this diff, I implement it. Reviewed By: mmmulani Differential Revision: D6306866 fbshipit-source-id: 7763df78676215c3dd0bd7a029497a6eca1873ab --- React/Views/RCTWKWebViewManager.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/React/Views/RCTWKWebViewManager.m b/React/Views/RCTWKWebViewManager.m index fb1db9cc3dc24f..a2f8df4a5fbd30 100644 --- a/React/Views/RCTWKWebViewManager.m +++ b/React/Views/RCTWKWebViewManager.m @@ -36,4 +36,6 @@ - (UIView *)view }]; } +RCT_REMAP_VIEW_PROPERTY(bounces, _webView.scrollView.bounces, BOOL) + @end From 1c3af598b163c8e02baa0bfa3455347ed869932f Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 16 Aug 2018 13:34:05 -0700 Subject: [PATCH 058/273] Implement 'scrollEnabled' prop Summary: @public The content of `WKWebView` renders within a scrollview. In this diff, I'm introducing the prop `scrollEnabled` to allow developers to control whether scrolling is enabled within the scroll view, or not. Reviewed By: mmmulani Differential Revision: D6307001 fbshipit-source-id: 5a199c6c3b8535e45a5a3cb6041e822bb7af2362 --- React/Views/RCTWKWebView.h | 1 + React/Views/RCTWKWebView.m | 5 +++++ React/Views/RCTWKWebViewManager.m | 3 +++ 3 files changed, 9 insertions(+) diff --git a/React/Views/RCTWKWebView.h b/React/Views/RCTWKWebView.h index d094b72d4ddeeb..ca1d3ae1936ed7 100644 --- a/React/Views/RCTWKWebView.h +++ b/React/Views/RCTWKWebView.h @@ -20,6 +20,7 @@ @property (nonatomic, copy) NSDictionary *source; @property (nonatomic, assign) BOOL messagingEnabled; @property (nonatomic, copy) NSString *injectedJavaScript; +@property (nonatomic, assign) BOOL scrollEnabled; - (void)postMessage:(NSString *)message; diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m index 2c9aef5e570ffd..63bab215932d7d 100644 --- a/React/Views/RCTWKWebView.m +++ b/React/Views/RCTWKWebView.m @@ -85,6 +85,11 @@ - (void)setSource:(NSDictionary *)source } } +- (void)setScrollEnabled:(BOOL)scrollEnabled +{ + _webView.scrollView.scrollEnabled = scrollEnabled; +} + - (void)postMessage:(NSString *)message { NSDictionary *eventInitDict = @{@"data": message}; diff --git a/React/Views/RCTWKWebViewManager.m b/React/Views/RCTWKWebViewManager.m index a2f8df4a5fbd30..5b71de0c7ac8b9 100644 --- a/React/Views/RCTWKWebViewManager.m +++ b/React/Views/RCTWKWebViewManager.m @@ -37,5 +37,8 @@ - (UIView *)view } RCT_REMAP_VIEW_PROPERTY(bounces, _webView.scrollView.bounces, BOOL) +RCT_CUSTOM_VIEW_PROPERTY(scrollEnabled, BOOL, RCTWKWebView) { + view.scrollEnabled = json == nil ? true : [RCTConvert BOOL: json]; +} @end From 566259880a9c866c0fce6a3cd199b2011c4ead44 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 16 Aug 2018 13:34:07 -0700 Subject: [PATCH 059/273] Implement 'decelerationRate' prop Summary: @public The content that renders within the `WKWebView` instance actually renders inside a `UIScrollView`. On that scroll view, we can adjust the `decelerationRate`, which controls how fast the view stops scrolling after the user lets go while scrolling. In this diff, I implemented the `decelerationRate` prop for `WKWebView`, which gets forwarded to the `UIScrollView` instance underlying the web view. **Note:** Even though we accept a floating point value for the deceleration rate, the native `UIScrollView` component only allows two inputs: 1. `UIScrollViewDecelerationRateNormal`: 0.998 2. `UIScrollViewDecelerationRateFast`: 0.99 As far as I know, it seems to just round up to the nearest valid `CGFloat` (or down if number > 0.998), for any invalid numbers. Reviewed By: mmmulani Differential Revision: D6307262 fbshipit-source-id: 98c4395702415aa36519f9e9bd84f043be3a5881 --- React/Views/RCTWKWebView.h | 1 + React/Views/RCTWKWebView.m | 9 ++++++++- React/Views/RCTWKWebViewManager.m | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/React/Views/RCTWKWebView.h b/React/Views/RCTWKWebView.h index ca1d3ae1936ed7..c42023d09460c2 100644 --- a/React/Views/RCTWKWebView.h +++ b/React/Views/RCTWKWebView.h @@ -21,6 +21,7 @@ @property (nonatomic, assign) BOOL messagingEnabled; @property (nonatomic, copy) NSString *injectedJavaScript; @property (nonatomic, assign) BOOL scrollEnabled; +@property (nonatomic, assign) CGFloat decelerationRate; - (void)postMessage:(NSString *)message; diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m index 63bab215932d7d..601651657d93f5 100644 --- a/React/Views/RCTWKWebView.m +++ b/React/Views/RCTWKWebView.m @@ -5,7 +5,7 @@ static NSString *const MessageHanderName = @"ReactNative"; -@interface RCTWKWebView () +@interface RCTWKWebView () @property (nonatomic, copy) RCTDirectEventBlock onLoadingStart; @property (nonatomic, copy) RCTDirectEventBlock onLoadingFinish; @property (nonatomic, copy) RCTDirectEventBlock onLoadingError; @@ -31,6 +31,7 @@ - (instancetype)initWithFrame:(CGRect)frame [wkWebViewConfig.userContentController addScriptMessageHandler: self name: MessageHanderName]; _webView = [[WKWebView alloc] initWithFrame:self.bounds configuration: wkWebViewConfig]; + _webView.scrollView.delegate = self; _webView.UIDelegate = self; _webView.navigationDelegate = self; [self addSubview:_webView]; @@ -85,6 +86,12 @@ - (void)setSource:(NSDictionary *)source } } + +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView +{ + scrollView.decelerationRate = _decelerationRate; +} + - (void)setScrollEnabled:(BOOL)scrollEnabled { _webView.scrollView.scrollEnabled = scrollEnabled; diff --git a/React/Views/RCTWKWebViewManager.m b/React/Views/RCTWKWebViewManager.m index 5b71de0c7ac8b9..8c234b11536019 100644 --- a/React/Views/RCTWKWebViewManager.m +++ b/React/Views/RCTWKWebViewManager.m @@ -41,4 +41,8 @@ - (UIView *)view view.scrollEnabled = json == nil ? true : [RCTConvert BOOL: json]; } +RCT_CUSTOM_VIEW_PROPERTY(decelerationRate, CGFloat, RCTWKWebView) { + view.decelerationRate = json == nil ? UIScrollViewDecelerationRateNormal : [RCTConvert CGFloat: json]; +} + @end From 1984f4bc2709f80065bb416b984684a2955b1467 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 16 Aug 2018 13:34:09 -0700 Subject: [PATCH 060/273] Implement 'injectJavaScript' method Summary: @public This diff introduces a method called `injectJavaScript(script)` on the React Native `` component. When called with a string, it evaluates that string as JavaScript within the web view. Reviewed By: shergin Differential Revision: D6367445 fbshipit-source-id: f68afeff42535dc991747f96a63f3c956faf13d3 --- React/Views/RCTWKWebView.h | 1 + React/Views/RCTWKWebView.m | 5 +++++ React/Views/RCTWKWebViewManager.m | 12 ++++++++++++ 3 files changed, 18 insertions(+) diff --git a/React/Views/RCTWKWebView.h b/React/Views/RCTWKWebView.h index c42023d09460c2..b0f073a67e10da 100644 --- a/React/Views/RCTWKWebView.h +++ b/React/Views/RCTWKWebView.h @@ -24,5 +24,6 @@ @property (nonatomic, assign) CGFloat decelerationRate; - (void)postMessage:(NSString *)message; +- (void)injectJavaScript:(NSString *)script; @end diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m index 601651657d93f5..4083f1a5fbdc98 100644 --- a/React/Views/RCTWKWebView.m +++ b/React/Views/RCTWKWebView.m @@ -255,4 +255,9 @@ - (void) webView:(WKWebView *)webView } } +- (void)injectJavaScript:(NSString *)script +{ + [self evaluateJS: script thenCall: nil]; +} + @end diff --git a/React/Views/RCTWKWebViewManager.m b/React/Views/RCTWKWebViewManager.m index 8c234b11536019..f6e3a037181d62 100644 --- a/React/Views/RCTWKWebViewManager.m +++ b/React/Views/RCTWKWebViewManager.m @@ -45,4 +45,16 @@ - (UIView *)view view.decelerationRate = json == nil ? UIScrollViewDecelerationRateNormal : [RCTConvert CGFloat: json]; } +RCT_EXPORT_METHOD(injectJavaScript:(nonnull NSNumber *)reactTag script:(NSString *)script) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + RCTWKWebView *view = viewRegistry[reactTag]; + if (![view isKindOfClass:[RCTWKWebView class]]) { + RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); + } else { + [view injectJavaScript:script]; + } + }]; +} + @end From 1b73e76ff374e45ee92f4866f963afff4978277e Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 16 Aug 2018 13:34:11 -0700 Subject: [PATCH 061/273] Implement 'goForward' and 'goBack' methods Summary: @public This diff implements the `goForward` and `goBack` methods on `WKWebView`. 1. `goForward` moves the web view one screen forward in the browser history. 1. `goBack` moves the web view one screen back in the browser history. Reviewed By: shergin Differential Revision: D6367495 fbshipit-source-id: e100ca00e92a6eaa30d2af1af642ba79a9c9feae --- React/Views/RCTWKWebView.h | 2 ++ React/Views/RCTWKWebView.m | 10 ++++++++++ React/Views/RCTWKWebViewManager.m | 24 ++++++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/React/Views/RCTWKWebView.h b/React/Views/RCTWKWebView.h index b0f073a67e10da..ce9b0734783b0c 100644 --- a/React/Views/RCTWKWebView.h +++ b/React/Views/RCTWKWebView.h @@ -25,5 +25,7 @@ - (void)postMessage:(NSString *)message; - (void)injectJavaScript:(NSString *)script; +- (void)goForward; +- (void)goBack; @end diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m index 4083f1a5fbdc98..b2dbc1203864fc 100644 --- a/React/Views/RCTWKWebView.m +++ b/React/Views/RCTWKWebView.m @@ -260,4 +260,14 @@ - (void)injectJavaScript:(NSString *)script [self evaluateJS: script thenCall: nil]; } +- (void)goForward +{ + [_webView goForward]; +} + +- (void)goBack +{ + [_webView goBack]; +} + @end diff --git a/React/Views/RCTWKWebViewManager.m b/React/Views/RCTWKWebViewManager.m index f6e3a037181d62..0fee19310997d3 100644 --- a/React/Views/RCTWKWebViewManager.m +++ b/React/Views/RCTWKWebViewManager.m @@ -57,4 +57,28 @@ - (UIView *)view }]; } +RCT_EXPORT_METHOD(goBack:(nonnull NSNumber *)reactTag) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + RCTWKWebView *view = viewRegistry[reactTag]; + if (![view isKindOfClass:[RCTWKWebView class]]) { + RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); + } else { + [view goBack]; + } + }]; +} + +RCT_EXPORT_METHOD(goForward:(nonnull NSNumber *)reactTag) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + RCTWKWebView *view = viewRegistry[reactTag]; + if (![view isKindOfClass:[RCTWKWebView class]]) { + RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); + } else { + [view goForward]; + } + }]; +} + @end From d0b5a38c69cae124e2574d4b753b80e65741777c Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 16 Aug 2018 13:34:14 -0700 Subject: [PATCH 062/273] Implement 'reload' and 'stopLoading' methods Summary: @public This diff implements the `reload` and `stopLoading` methods for `WKWebView`. Their functionality is self-explanatory. Reviewed By: shergin Differential Revision: D6369292 fbshipit-source-id: ba176f4406e0a67606406f36dd66f7615f4796c3 --- React/Views/RCTWKWebView.h | 2 ++ React/Views/RCTWKWebView.m | 20 ++++++++++++++++++++ React/Views/RCTWKWebViewManager.m | 24 ++++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/React/Views/RCTWKWebView.h b/React/Views/RCTWKWebView.h index ce9b0734783b0c..4e749d59c5a6c2 100644 --- a/React/Views/RCTWKWebView.h +++ b/React/Views/RCTWKWebView.h @@ -27,5 +27,7 @@ - (void)injectJavaScript:(NSString *)script; - (void)goForward; - (void)goBack; +- (void)reload; +- (void)stopLoading; @end diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m index b2dbc1203864fc..b33dffefea98a9 100644 --- a/React/Views/RCTWKWebView.m +++ b/React/Views/RCTWKWebView.m @@ -270,4 +270,24 @@ - (void)goBack [_webView goBack]; } +- (void)reload +{ + /** + * When the initial load fails due to network connectivity issues, + * [_webView reload] doesn't reload the webpage. Therefore, we must + * manually call [_webView loadRequest:request]. + */ + NSURLRequest *request = [RCTConvert NSURLRequest:self.source]; + if (request.URL && !_webView.URL.absoluteString.length) { + [_webView loadRequest:request]; + } + else { + [_webView reload]; + } +} + +- (void)stopLoading +{ + [_webView stopLoading]; +} @end diff --git a/React/Views/RCTWKWebViewManager.m b/React/Views/RCTWKWebViewManager.m index 0fee19310997d3..918bc736a03803 100644 --- a/React/Views/RCTWKWebViewManager.m +++ b/React/Views/RCTWKWebViewManager.m @@ -81,4 +81,28 @@ - (UIView *)view }]; } +RCT_EXPORT_METHOD(reload:(nonnull NSNumber *)reactTag) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + RCTWKWebView *view = viewRegistry[reactTag]; + if (![view isKindOfClass:[RCTWKWebView class]]) { + RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); + } else { + [view reload]; + } + }]; +} + +RCT_EXPORT_METHOD(stopLoading:(nonnull NSNumber *)reactTag) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + RCTWKWebView *view = viewRegistry[reactTag]; + if (![view isKindOfClass:[RCTWKWebView class]]) { + RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); + } else { + [view stopLoading]; + } + }]; +} + @end From 0fa5bd8b9bbda59cfa56b177840899d00ff8494a Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 16 Aug 2018 13:34:16 -0700 Subject: [PATCH 063/273] Implement 'onShouldStartLoadWithRequest' prop Summary: @public This diff introduces the native backend for a new WKWebView prop: `onShouldStartLoadWithRequest`. In the final component, the behaviour will be as follows: Whenever the user navigates around in the web view, we call `onShouldStartLoadWithRequest` with the navigation event. If `onShouldStartLoadWithRequest` returns `true`, we continue the navigation. Otherwise, we abort it. Reviewed By: shergin Differential Revision: D6370317 fbshipit-source-id: e3cdd7e2a755125aebdb6df67e7b39116228bdfb --- React/Views/RCTWKWebView.h | 5 ++++ React/Views/RCTWKWebView.m | 15 ++++++++++ React/Views/RCTWKWebViewManager.m | 46 ++++++++++++++++++++++++++++++- 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/React/Views/RCTWKWebView.h b/React/Views/RCTWKWebView.h index 4e749d59c5a6c2..cb4971537e0e90 100644 --- a/React/Views/RCTWKWebView.h +++ b/React/Views/RCTWKWebView.h @@ -12,6 +12,11 @@ @class RCTWKWebView; @protocol RCTWKWebViewDelegate + +- (BOOL)webView:(RCTWKWebView *)webView +shouldStartLoadForRequest:(NSMutableDictionary *)request + withCallback:(RCTDirectEventBlock)callback; + @end @interface RCTWKWebView : RCTView diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m index b33dffefea98a9..15fdd844e7e2ae 100644 --- a/React/Views/RCTWKWebView.m +++ b/React/Views/RCTWKWebView.m @@ -9,6 +9,7 @@ @interface RCTWKWebView () *event = [self baseEvent]; + [event addEntriesFromDictionary: @{ + @"url": (request.URL).absoluteString, + @"navigationType": navigationTypes[@(navigationType)] + }]; + if (![self.delegate webView:self + shouldStartLoadForRequest:event + withCallback:_onShouldStartLoadWithRequest]) { + decisionHandler(WKNavigationResponsePolicyCancel); + return; + } + } + if (_onLoadingStart) { // We have this check to filter out iframe requests and whatnot BOOL isTopFrame = [request.URL isEqual:request.mainDocumentURL]; diff --git a/React/Views/RCTWKWebViewManager.m b/React/Views/RCTWKWebViewManager.m index 918bc736a03803..20244c11f0e63f 100644 --- a/React/Views/RCTWKWebViewManager.m +++ b/React/Views/RCTWKWebViewManager.m @@ -3,19 +3,29 @@ #import "RCTUIManager.h" #import "RCTWKWebView.h" +@interface RCTWKWebViewManager () +@end + @implementation RCTWKWebViewManager +{ + NSConditionLock *_shouldStartLoadLock; + BOOL _shouldStartLoad; +} RCT_EXPORT_MODULE() - (UIView *)view { - return [RCTWKWebView new]; + RCTWKWebView *webView = [RCTWKWebView new]; + webView.delegate = self; + return webView; } RCT_EXPORT_VIEW_PROPERTY(source, NSDictionary) RCT_EXPORT_VIEW_PROPERTY(onLoadingStart, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onLoadingFinish, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onLoadingError, RCTDirectEventBlock) +RCT_EXPORT_VIEW_PROPERTY(onShouldStartLoadWithRequest, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(injectedJavaScript, NSString) /** @@ -105,4 +115,38 @@ - (UIView *)view }]; } +#pragma mark - Exported synchronous methods + +- (BOOL) webView:(RCTWKWebView *)webView +shouldStartLoadForRequest:(NSMutableDictionary *)request + withCallback:(RCTDirectEventBlock)callback +{ + _shouldStartLoadLock = [[NSConditionLock alloc] initWithCondition:arc4random()]; + _shouldStartLoad = YES; + request[@"lockIdentifier"] = @(_shouldStartLoadLock.condition); + callback(request); + + // Block the main thread for a maximum of 250ms until the JS thread returns + if ([_shouldStartLoadLock lockWhenCondition:0 beforeDate:[NSDate dateWithTimeIntervalSinceNow:.25]]) { + BOOL returnValue = _shouldStartLoad; + [_shouldStartLoadLock unlock]; + _shouldStartLoadLock = nil; + return returnValue; + } else { + RCTLogWarn(@"Did not receive response to shouldStartLoad in time, defaulting to YES"); + return YES; + } +} + +RCT_EXPORT_METHOD(startLoadWithResult:(BOOL)result lockIdentifier:(NSInteger)lockIdentifier) +{ + if ([_shouldStartLoadLock tryLockWhenCondition:lockIdentifier]) { + _shouldStartLoad = result; + [_shouldStartLoadLock unlockWithCondition:0]; + } else { + RCTLogWarn(@"startLoadWithResult invoked with invalid lockIdentifier: " + "got %lld, expected %lld", (long long)lockIdentifier, (long long)_shouldStartLoadLock.condition); + } +} + @end From 527792ac8edae40ce65d0bee65c6d68fbc2474a1 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 16 Aug 2018 13:34:18 -0700 Subject: [PATCH 064/273] Implement 'allowsInlineMediaPlayback` prop Summary: For iPhones with small screen sizes (e.g: iPhone 5s), inside the `` component, videos will play in fullscreen mode. In this diff, I introduce a prop called `allowsInlineMediaPlayback` that when set to true, will allow videos to play inline. **Note:** For videos to play inline, the HTML video element must also have a `playsinline` attribute on it. Reviewed By: shergin Differential Revision: D6379770 fbshipit-source-id: a0130720ffede6c24a90cad0c97a75b657d77017 --- .../Components/WKWebView/WKWebView.ios.js | 22 +++++- React/Views/RCTWKWebView.h | 2 + React/Views/RCTWKWebView.m | 73 +++++++++++++------ React/Views/RCTWKWebViewManager.m | 6 +- 4 files changed, 78 insertions(+), 25 deletions(-) diff --git a/Libraries/Components/WKWebView/WKWebView.ios.js b/Libraries/Components/WKWebView/WKWebView.ios.js index d1af14bfebd6e7..d097ea48efe0ce 100644 --- a/Libraries/Components/WKWebView/WKWebView.ios.js +++ b/Libraries/Components/WKWebView/WKWebView.ios.js @@ -9,6 +9,26 @@ * @providesModule WKWebView */ +const React = require('react'); + const requireNativeComponent = require('requireNativeComponent'); -module.exports = requireNativeComponent('RCTWKWebView'); +const RCTWKWebView = requireNativeComponent('RCTWKWebView'); + +type RCTWKWebViewProps = { + allowsInlineMediaPlayback?: boolean, +}; + +class WKWebView extends React.Component { + componentWillReceiveProps(nextProps: RCTWKWebViewProps) { + if (this.props.allowsInlineMediaPlayback !== nextProps.allowsInlineMediaPlayback) { + console.error('Changes to property allowsInlineMediaPlayback do nothing after the initial render.'); + } + } + + render() { + return ; + } +} + +module.exports = WKWebView; diff --git a/React/Views/RCTWKWebView.h b/React/Views/RCTWKWebView.h index cb4971537e0e90..b19b9d10f2fac7 100644 --- a/React/Views/RCTWKWebView.h +++ b/React/Views/RCTWKWebView.h @@ -27,6 +27,8 @@ shouldStartLoadForRequest:(NSMutableDictionary *)request @property (nonatomic, copy) NSString *injectedJavaScript; @property (nonatomic, assign) BOOL scrollEnabled; @property (nonatomic, assign) CGFloat decelerationRate; +@property (nonatomic, assign) BOOL allowsInlineMediaPlayback; +@property (nonatomic, assign) BOOL bounces; - (void)postMessage:(NSString *)message; - (void)injectJavaScript:(NSString *)script; diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m index 15fdd844e7e2ae..31ba395201145f 100644 --- a/React/Views/RCTWKWebView.m +++ b/React/Views/RCTWKWebView.m @@ -27,17 +27,30 @@ - (instancetype)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { super.backgroundColor = [UIColor clearColor]; + _bounces = YES; + _scrollEnabled = YES; + } + return self; +} + +- (void)didMoveToWindow +{ + if (self.window != nil) { WKWebViewConfiguration *wkWebViewConfig = [WKWebViewConfiguration new]; wkWebViewConfig.userContentController = [WKUserContentController new]; [wkWebViewConfig.userContentController addScriptMessageHandler: self name: MessageHanderName]; + wkWebViewConfig.allowsInlineMediaPlayback = _allowsInlineMediaPlayback; _webView = [[WKWebView alloc] initWithFrame:self.bounds configuration: wkWebViewConfig]; _webView.scrollView.delegate = self; _webView.UIDelegate = self; _webView.navigationDelegate = self; + _webView.scrollView.scrollEnabled = _scrollEnabled; + _webView.scrollView.bounces = _bounces; [self addSubview:_webView]; + + [self visitSource]; } - return self; } /** @@ -59,32 +72,39 @@ - (void)setSource:(NSDictionary *)source if (![_source isEqualToDictionary:source]) { _source = [source copy]; - // Check for a static html source first - NSString *html = [RCTConvert NSString:source[@"html"]]; - if (html) { - NSURL *baseURL = [RCTConvert NSURL:source[@"baseUrl"]]; - if (!baseURL) { - baseURL = [NSURL URLWithString:@"about:blank"]; - } - [_webView loadHTMLString:html baseURL:baseURL]; - return; + if (_webView != nil) { + [self visitSource]; } + } +} - NSURLRequest *request = [RCTConvert NSURLRequest:source]; - // Because of the way React works, as pages redirect, we actually end up - // passing the redirect urls back here, so we ignore them if trying to load - // the same url. We'll expose a call to 'reload' to allow a user to load - // the existing page. - if ([request.URL isEqual:_webView.URL]) { - return; - } - if (!request.URL) { - // Clear the webview - [_webView loadHTMLString:@"" baseURL:nil]; - return; +- (void)visitSource +{ + // Check for a static html source first + NSString *html = [RCTConvert NSString:_source[@"html"]]; + if (html) { + NSURL *baseURL = [RCTConvert NSURL:_source[@"baseUrl"]]; + if (!baseURL) { + baseURL = [NSURL URLWithString:@"about:blank"]; } - [_webView loadRequest:request]; + [_webView loadHTMLString:html baseURL:baseURL]; + return; } + + NSURLRequest *request = [RCTConvert NSURLRequest:_source]; + // Because of the way React works, as pages redirect, we actually end up + // passing the redirect urls back here, so we ignore them if trying to load + // the same url. We'll expose a call to 'reload' to allow a user to load + // the existing page. + if ([request.URL isEqual:_webView.URL]) { + return; + } + if (!request.URL) { + // Clear the webview + [_webView loadHTMLString:@"" baseURL:nil]; + return; + } + [_webView loadRequest:request]; } @@ -95,6 +115,7 @@ - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView - (void)setScrollEnabled:(BOOL)scrollEnabled { + _scrollEnabled = scrollEnabled; _webView.scrollView.scrollEnabled = scrollEnabled; } @@ -305,4 +326,10 @@ - (void)stopLoading { [_webView stopLoading]; } + +- (void)setBounces:(BOOL)bounces +{ + _bounces = bounces; + _webView.scrollView.bounces = bounces; +} @end diff --git a/React/Views/RCTWKWebViewManager.m b/React/Views/RCTWKWebViewManager.m index 20244c11f0e63f..eef5b4f0612d53 100644 --- a/React/Views/RCTWKWebViewManager.m +++ b/React/Views/RCTWKWebViewManager.m @@ -27,6 +27,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(onLoadingError, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onShouldStartLoadWithRequest, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(injectedJavaScript, NSString) +RCT_EXPORT_VIEW_PROPERTY(allowsInlineMediaPlayback, BOOL) /** * Expose methods to enable messaging the webview. @@ -46,7 +47,10 @@ - (UIView *)view }]; } -RCT_REMAP_VIEW_PROPERTY(bounces, _webView.scrollView.bounces, BOOL) +RCT_CUSTOM_VIEW_PROPERTY(bounces, BOOL, RCTWKWebView) { + view.bounces = json == nil ? true : [RCTConvert BOOL: json]; +} + RCT_CUSTOM_VIEW_PROPERTY(scrollEnabled, BOOL, RCTWKWebView) { view.scrollEnabled = json == nil ? true : [RCTConvert BOOL: json]; } From ee971a76fae35edb624b4fa30017085264e92e77 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 16 Aug 2018 13:34:20 -0700 Subject: [PATCH 065/273] Implement 'mediaPlaybackRequiresUserAction' prop Summary: HTML video elements can have the `autoplay` attribute, which forces them to play automatically whenever they load on the page. In this diff, I introduce a new prop `mediaPlaybackRequiresUserAction`, which allows us to control whether video or audio element autoplays even when `autoplay` is set. Reviewed By: shergin Differential Revision: D6382256 fbshipit-source-id: 617508653910d600bc43f7f68c6dfd17ab1b6dd8 --- Libraries/Components/WKWebView/WKWebView.ios.js | 10 ++++++++-- React/Views/RCTWKWebView.h | 1 + React/Views/RCTWKWebView.m | 3 +++ React/Views/RCTWKWebViewManager.m | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Libraries/Components/WKWebView/WKWebView.ios.js b/Libraries/Components/WKWebView/WKWebView.ios.js index d097ea48efe0ce..c13d463a32d4d6 100644 --- a/Libraries/Components/WKWebView/WKWebView.ios.js +++ b/Libraries/Components/WKWebView/WKWebView.ios.js @@ -17,12 +17,18 @@ const RCTWKWebView = requireNativeComponent('RCTWKWebView'); type RCTWKWebViewProps = { allowsInlineMediaPlayback?: boolean, + mediaPlaybackRequiresUserAction?: boolean, }; class WKWebView extends React.Component { componentWillReceiveProps(nextProps: RCTWKWebViewProps) { - if (this.props.allowsInlineMediaPlayback !== nextProps.allowsInlineMediaPlayback) { - console.error('Changes to property allowsInlineMediaPlayback do nothing after the initial render.'); + this.showRedboxOnPropChanges(nextProps, 'allowsInlineMediaPlayback'); + this.showRedboxOnPropChanges(nextProps, 'mediaPlaybackRequiresUserAction'); + } + + showRedboxOnPropChanges(nextProps: RCTWKWebViewProps, propName: string) { + if (this.props[propName] !== nextProps[propName]) { + console.error(`Changes to property ${propName} do nothing after the initial render.`); } } diff --git a/React/Views/RCTWKWebView.h b/React/Views/RCTWKWebView.h index b19b9d10f2fac7..9b12d793d0c2b3 100644 --- a/React/Views/RCTWKWebView.h +++ b/React/Views/RCTWKWebView.h @@ -29,6 +29,7 @@ shouldStartLoadForRequest:(NSMutableDictionary *)request @property (nonatomic, assign) CGFloat decelerationRate; @property (nonatomic, assign) BOOL allowsInlineMediaPlayback; @property (nonatomic, assign) BOOL bounces; +@property (nonatomic, assign) BOOL mediaPlaybackRequiresUserAction; - (void)postMessage:(NSString *)message; - (void)injectJavaScript:(NSString *)script; diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m index 31ba395201145f..e6c2251b70fd8c 100644 --- a/React/Views/RCTWKWebView.m +++ b/React/Views/RCTWKWebView.m @@ -40,6 +40,9 @@ - (void)didMoveToWindow wkWebViewConfig.userContentController = [WKUserContentController new]; [wkWebViewConfig.userContentController addScriptMessageHandler: self name: MessageHanderName]; wkWebViewConfig.allowsInlineMediaPlayback = _allowsInlineMediaPlayback; + wkWebViewConfig.mediaTypesRequiringUserActionForPlayback = _mediaPlaybackRequiresUserAction + ? WKAudiovisualMediaTypeAll + : WKAudiovisualMediaTypeNone; _webView = [[WKWebView alloc] initWithFrame:self.bounds configuration: wkWebViewConfig]; _webView.scrollView.delegate = self; diff --git a/React/Views/RCTWKWebViewManager.m b/React/Views/RCTWKWebViewManager.m index eef5b4f0612d53..5f6be7e9aeed57 100644 --- a/React/Views/RCTWKWebViewManager.m +++ b/React/Views/RCTWKWebViewManager.m @@ -28,7 +28,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(onShouldStartLoadWithRequest, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(injectedJavaScript, NSString) RCT_EXPORT_VIEW_PROPERTY(allowsInlineMediaPlayback, BOOL) - +RCT_EXPORT_VIEW_PROPERTY(mediaPlaybackRequiresUserAction, BOOL) /** * Expose methods to enable messaging the webview. */ From d29c2534b8c51b45f64477823f3d4b2d7101e187 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 16 Aug 2018 13:34:22 -0700 Subject: [PATCH 066/273] Implement 'dataDetectorTypes' prop Summary: When text is rendered in `WKWebView` WebKit component, the component itself can detect things like phone numbers, flight numbers, links, etc. and render them with additional functionality. For example, when the text `apple.com` is detected, if the `link` data detector type is enabled, the web view will actually render a link that takes the user to the Apple home page. In this diff, I implement the `dataDetectorTypes` prop. The data detector types supported are: 1. phoneNumber 1. link 1. address 1. calendarEvent 1. trackingNumber 1. flightNumber 1. lookupSuggestion These enums are documented in the [[ https://developer.apple.com/documentation/webkit/wkdatadetectortypes | WKDataDetectorTypes docs ]]. Reviewed By: shergin Differential Revision: D6392546 fbshipit-source-id: 4dd373f0ac52f898163cd959eeef6672e55b42a6 --- Libraries/Components/WKWebView/WKWebView.ios.js | 2 ++ React/Base/RCTConvert.h | 2 ++ React/Base/RCTConvert.m | 12 ++++++++++++ React/Views/RCTWKWebView.h | 2 ++ React/Views/RCTWKWebView.m | 2 +- React/Views/RCTWKWebViewManager.m | 2 ++ React/Views/RCTWebViewManager.m | 4 ++-- 7 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Libraries/Components/WKWebView/WKWebView.ios.js b/Libraries/Components/WKWebView/WKWebView.ios.js index c13d463a32d4d6..ec4e635e28102a 100644 --- a/Libraries/Components/WKWebView/WKWebView.ios.js +++ b/Libraries/Components/WKWebView/WKWebView.ios.js @@ -18,12 +18,14 @@ const RCTWKWebView = requireNativeComponent('RCTWKWebView'); type RCTWKWebViewProps = { allowsInlineMediaPlayback?: boolean, mediaPlaybackRequiresUserAction?: boolean, + dataDetectorTypes?: boolean, }; class WKWebView extends React.Component { componentWillReceiveProps(nextProps: RCTWKWebViewProps) { this.showRedboxOnPropChanges(nextProps, 'allowsInlineMediaPlayback'); this.showRedboxOnPropChanges(nextProps, 'mediaPlaybackRequiresUserAction'); + this.showRedboxOnPropChanges(nextProps, 'dataDetectorTypes'); } showRedboxOnPropChanges(nextProps: RCTWKWebViewProps, propName: string) { diff --git a/React/Base/RCTConvert.h b/React/Base/RCTConvert.h index 5780c5f5f676a8..1f66328ea76d18 100644 --- a/React/Base/RCTConvert.h +++ b/React/Base/RCTConvert.h @@ -15,6 +15,7 @@ #import #import #import +#import /** * This class provides a collection of conversion functions for mapping @@ -68,6 +69,7 @@ typedef NSURL RCTFileURL; + (UIReturnKeyType)UIReturnKeyType:(id)json; #if !TARGET_OS_TV + (UIDataDetectorTypes)UIDataDetectorTypes:(id)json; ++ (WKDataDetectorTypes)WKDataDetectorTypes:(id)json; #endif + (UIViewContentMode)UIViewContentMode:(id)json; diff --git a/React/Base/RCTConvert.m b/React/Base/RCTConvert.m index 7528259fda00ad..90335e9894a338 100644 --- a/React/Base/RCTConvert.m +++ b/React/Base/RCTConvert.m @@ -361,6 +361,18 @@ + (NSLocale *)NSLocale:(id)json @"none": @(UIDataDetectorTypeNone), @"all": @(UIDataDetectorTypeAll), }), UIDataDetectorTypePhoneNumber, unsignedLongLongValue) + +RCT_MULTI_ENUM_CONVERTER(WKDataDetectorTypes, (@{ + @"phoneNumber": @(WKDataDetectorTypePhoneNumber), + @"link": @(WKDataDetectorTypeLink), + @"address": @(WKDataDetectorTypeAddress), + @"calendarEvent": @(WKDataDetectorTypeCalendarEvent), + @"trackingNumber": @(WKDataDetectorTypeTrackingNumber), + @"flightNumber": @(WKDataDetectorTypeFlightNumber), + @"lookupSuggestion": @(WKDataDetectorTypeLookupSuggestion), + @"none": @(WKDataDetectorTypeNone), + @"all": @(WKDataDetectorTypeAll), + }), WKDataDetectorTypePhoneNumber, unsignedLongLongValue) #endif RCT_ENUM_CONVERTER(UIKeyboardAppearance, (@{ diff --git a/React/Views/RCTWKWebView.h b/React/Views/RCTWKWebView.h index 9b12d793d0c2b3..e9143033c7d0a3 100644 --- a/React/Views/RCTWKWebView.h +++ b/React/Views/RCTWKWebView.h @@ -8,6 +8,7 @@ */ #import +#import @class RCTWKWebView; @@ -30,6 +31,7 @@ shouldStartLoadForRequest:(NSMutableDictionary *)request @property (nonatomic, assign) BOOL allowsInlineMediaPlayback; @property (nonatomic, assign) BOOL bounces; @property (nonatomic, assign) BOOL mediaPlaybackRequiresUserAction; +@property (nonatomic, assign) WKDataDetectorTypes dataDetectorTypes; - (void)postMessage:(NSString *)message; - (void)injectJavaScript:(NSString *)script; diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m index e6c2251b70fd8c..8cb16175f13ca3 100644 --- a/React/Views/RCTWKWebView.m +++ b/React/Views/RCTWKWebView.m @@ -1,5 +1,4 @@ #import "RCTWKWebView.h" -#import #import #import "RCTAutoInsetsProtocol.h" @@ -43,6 +42,7 @@ - (void)didMoveToWindow wkWebViewConfig.mediaTypesRequiringUserActionForPlayback = _mediaPlaybackRequiresUserAction ? WKAudiovisualMediaTypeAll : WKAudiovisualMediaTypeNone; + wkWebViewConfig.dataDetectorTypes = _dataDetectorTypes; _webView = [[WKWebView alloc] initWithFrame:self.bounds configuration: wkWebViewConfig]; _webView.scrollView.delegate = self; diff --git a/React/Views/RCTWKWebViewManager.m b/React/Views/RCTWKWebViewManager.m index 5f6be7e9aeed57..b3b0f0b43cbed8 100644 --- a/React/Views/RCTWKWebViewManager.m +++ b/React/Views/RCTWKWebViewManager.m @@ -29,6 +29,8 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(injectedJavaScript, NSString) RCT_EXPORT_VIEW_PROPERTY(allowsInlineMediaPlayback, BOOL) RCT_EXPORT_VIEW_PROPERTY(mediaPlaybackRequiresUserAction, BOOL) +RCT_EXPORT_VIEW_PROPERTY(dataDetectorTypes, WKDataDetectorTypes) + /** * Expose methods to enable messaging the webview. */ diff --git a/React/Views/RCTWebViewManager.m b/React/Views/RCTWebViewManager.m index 8f4ef9b0f4f793..3e7d0317b6dd2a 100644 --- a/React/Views/RCTWebViewManager.m +++ b/React/Views/RCTWebViewManager.m @@ -63,8 +63,8 @@ - (UIView *)view RCT_EXPORT_METHOD(goForward:(nonnull NSNumber *)reactTag) { - [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { - id view = viewRegistry[reactTag]; + [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); } else { From 0009d095d9fd056395dd32016d548f8385fdf948 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 16 Aug 2018 13:34:24 -0700 Subject: [PATCH 067/273] Implement 'backgroundColor' style Summary: @public This diff implements background colors for the `RCTWKWebView` component by proxying the background color prop to the underlying `WKWebView` and its underlying `UIScrollView`. There's few differences between `backgroundColor` in `RCTWebView` and `RCTWKWebView` implementations: 1. With `UIWebView,` the background color gets applied after the page loads. With `WKWebView`, this isn't necessarily true. This results in a white flicker on solid backgrounds because sometimes, the background color is set before the page loads. This video illustrates the problem: https://our.intern.facebook.com/intern/px/p/9QBH 1. As far as I can tell, `WKWebView` doesn't handle transparent backgrounds correctly. Either that, or I could be setting the background color incorrectly. I set the background color to `rgba(1, 1, 1, 0.5)` and recorded how both `RCTWebView` and `RCTWKWebView` render. These two videos indicate the differences: **RCTWebView: Lighter background** https://pxl.cl/9R13 **RCTWKWebView: Darker background** https://pxl.cl/9R1b I tried to replicate this on the web. According to [[ https://our.intern.facebook.com/intern/fiddle/zCHu/ | this fiddle ]], `RCTWebView` is correct. Clearly, RCTWKWebView is rendering transparent backgrounds a bit darker than necessary. This doesn't seem simple to debug, so I've created a task to document this work: T23815343. I'll get to it eventually. Reviewed By: shergin Differential Revision: D6398209 fbshipit-source-id: 1812cb68133bc18a3278f6b328d7b085362528b0 --- React/Views/RCTWKWebView.m | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m index 8cb16175f13ca3..0a55fdccd6c584 100644 --- a/React/Views/RCTWKWebView.m +++ b/React/Views/RCTWKWebView.m @@ -15,6 +15,7 @@ @interface RCTWKWebView () Date: Thu, 16 Aug 2018 13:34:26 -0700 Subject: [PATCH 068/273] Implement 'automaticallyAdjustContentInsets' and 'contentInset' props Summary: @public This diff introduces two new props: 1. **automaticallyAdjustContentInsets**: Controls whether to adjust the content inset for web views that are placed behind a navigation bar, tab bar, or toolbar. The default value is true. 1. **contentInset**: The amount by which the web view content is inset from the edges of the scroll view. Defaults to {top: 0, left: 0, bottom: 0, right: 0}. **Note:** There're some inconsistencies between how `UIWebView` and `WKWebView` render web pages with respect to the `contentInset` property. These two videos illustrate the problem: **UIWebView** [[ P58674349 | Playground.js ]] https://pxl.cl/9R9V **WKWebView** [[ P58674348 | Playground.js ]] https://pxl.cl/9R9W Here's a stack overflow answer describing the problem: https://stackoverflow.com/a/35472603. Reviewed By: shergin Differential Revision: D6432181 fbshipit-source-id: aee6dac65d28435381ebec90519474b4707c7bab --- React/Views/RCTWKWebView.h | 2 ++ React/Views/RCTWKWebView.m | 26 +++++++++++++++++++++++++- React/Views/RCTWKWebViewManager.m | 2 ++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/React/Views/RCTWKWebView.h b/React/Views/RCTWKWebView.h index e9143033c7d0a3..62c1371085515e 100644 --- a/React/Views/RCTWKWebView.h +++ b/React/Views/RCTWKWebView.h @@ -32,6 +32,8 @@ shouldStartLoadForRequest:(NSMutableDictionary *)request @property (nonatomic, assign) BOOL bounces; @property (nonatomic, assign) BOOL mediaPlaybackRequiresUserAction; @property (nonatomic, assign) WKDataDetectorTypes dataDetectorTypes; +@property (nonatomic, assign) UIEdgeInsets contentInset; +@property (nonatomic, assign) BOOL automaticallyAdjustContentInsets; - (void)postMessage:(NSString *)message; - (void)injectJavaScript:(NSString *)script; diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m index 0a55fdccd6c584..2488ff209a9e78 100644 --- a/React/Views/RCTWKWebView.m +++ b/React/Views/RCTWKWebView.m @@ -4,7 +4,7 @@ static NSString *const MessageHanderName = @"ReactNative"; -@interface RCTWKWebView () +@interface RCTWKWebView () @property (nonatomic, copy) RCTDirectEventBlock onLoadingStart; @property (nonatomic, copy) RCTDirectEventBlock onLoadingFinish; @property (nonatomic, copy) RCTDirectEventBlock onLoadingError; @@ -29,6 +29,8 @@ - (instancetype)initWithFrame:(CGRect)frame super.backgroundColor = [UIColor clearColor]; _bounces = YES; _scrollEnabled = YES; + _automaticallyAdjustContentInsets = YES; + _contentInset = UIEdgeInsetsZero; } return self; } @@ -51,6 +53,13 @@ - (void)didMoveToWindow _webView.navigationDelegate = self; _webView.scrollView.scrollEnabled = _scrollEnabled; _webView.scrollView.bounces = _bounces; + +#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */ + if ([_webView.scrollView respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) { + _webView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } +#endif + [self addSubview:_webView]; [self visitSource]; @@ -95,6 +104,21 @@ - (void)setSource:(NSDictionary *)source } } +- (void)setContentInset:(UIEdgeInsets)contentInset +{ + _contentInset = contentInset; + [RCTView autoAdjustInsetsForView:self + withScrollView:_webView.scrollView + updateOffset:NO]; +} + +- (void)refreshContentInset +{ + [RCTView autoAdjustInsetsForView:self + withScrollView:_webView.scrollView + updateOffset:YES]; +} + - (void)visitSource { // Check for a static html source first diff --git a/React/Views/RCTWKWebViewManager.m b/React/Views/RCTWKWebViewManager.m index b3b0f0b43cbed8..f0380185510285 100644 --- a/React/Views/RCTWKWebViewManager.m +++ b/React/Views/RCTWKWebViewManager.m @@ -30,6 +30,8 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(allowsInlineMediaPlayback, BOOL) RCT_EXPORT_VIEW_PROPERTY(mediaPlaybackRequiresUserAction, BOOL) RCT_EXPORT_VIEW_PROPERTY(dataDetectorTypes, WKDataDetectorTypes) +RCT_EXPORT_VIEW_PROPERTY(contentInset, UIEdgeInsets) +RCT_EXPORT_VIEW_PROPERTY(automaticallyAdjustContentInsets, BOOL) /** * Expose methods to enable messaging the webview. From f46dbc2a23f822204bf94cc735955cf9e1e6a5d7 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 16 Aug 2018 13:34:29 -0700 Subject: [PATCH 069/273] Move WKWebView into WebView.ios.js Summary: @public This diff adds the `useWebKit` property to the `` React Native component. On iOS, when this property is true, we use `RCTWKWebView`. Otherwise, we use `RCTWebView`. On Android, this property does nothing. Reviewed By: shergin Differential Revision: D6423374 fbshipit-source-id: 006bfaaf12984fac0174c0b5bb897c009c026cd0 --- .../Components/WKWebView/WKWebView.android.js | 22 ----- .../Components/WebView/WebView.android.js | 6 ++ Libraries/Components/WebView/WebView.ios.js | 80 ++++++++++++++++--- 3 files changed, 77 insertions(+), 31 deletions(-) delete mode 100644 Libraries/Components/WKWebView/WKWebView.android.js diff --git a/Libraries/Components/WKWebView/WKWebView.android.js b/Libraries/Components/WKWebView/WKWebView.android.js deleted file mode 100644 index a4cab312304c75..00000000000000 --- a/Libraries/Components/WKWebView/WKWebView.android.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow - * @providesModule WKWebView - */ - -const React = require('React'); -const View = require('View'); -const Text = require('Text'); - -module.exports = () => { - return ( - - Android version not implemented. - - ); -}; diff --git a/Libraries/Components/WebView/WebView.android.js b/Libraries/Components/WebView/WebView.android.js index 4d4b65fb11fdc8..bed2179734579a 100644 --- a/Libraries/Components/WebView/WebView.android.js +++ b/Libraries/Components/WebView/WebView.android.js @@ -109,6 +109,12 @@ class WebView extends React.Component { PropTypes.number, ]), + /** + * If true, use WKWebView instead of UIWebView. + * @platform ios + */ + useWebKit: PropTypes.bool, + /** * Used on Android only, JS is enabled by default for WebView on iOS * @platform android diff --git a/Libraries/Components/WebView/WebView.ios.js b/Libraries/Components/WebView/WebView.ios.js index 413cae03950ff9..f158addaaefdbe 100644 --- a/Libraries/Components/WebView/WebView.ios.js +++ b/Libraries/Components/WebView/WebView.ios.js @@ -32,6 +32,7 @@ const requireNativeComponent = require('requireNativeComponent'); const resolveAssetSource = require('resolveAssetSource'); const RCTWebViewManager = require('NativeModules').WebViewManager; +const RCTWKWebViewManager = require('NativeModules').WKWebViewManager; const BGWASH = 'rgba(255,255,255,0.8)'; const RCT_WEBVIEW_REF = 'webview'; @@ -66,6 +67,9 @@ const DataDetectorTypes = [ 'link', 'address', 'calendarEvent', + 'trackingNumber', + 'flightNumber', + 'lookupSuggestion', 'none', 'all', ]; @@ -162,6 +166,12 @@ class WebView extends React.Component { PropTypes.number, ]), + /** + * If true, use WKWebView instead of UIWebView. + * @platform ios + */ + useWebKit: PropTypes.bool, + /** * Function that returns a view to show if there's an error. */ @@ -264,6 +274,11 @@ class WebView extends React.Component { * - `'none'` * - `'all'` * + * With the new WebKit implementation, we have three new values: + * - `'trackingNumber'`, + * - `'flightNumber'`, + * - `'lookupSuggestion'`, + * * @platform ios */ dataDetectorTypes: PropTypes.oneOfType([ @@ -433,7 +448,13 @@ class WebView extends React.Component { const nativeConfig = this.props.nativeConfig || {}; - const viewManager = nativeConfig.viewManager || RCTWebViewManager; + let viewManager = nativeConfig.viewManager; + + if (this.props.useWebKit) { + viewManager = viewManager || RCTWKWebViewManager; + } else { + viewManager = viewManager || RCTWebViewManager; + } const compiledWhitelist = [ 'about:blank', @@ -474,7 +495,13 @@ class WebView extends React.Component { const messagingEnabled = typeof this.props.onMessage === 'function'; - const NativeWebView = nativeConfig.component || RCTWebView; + let NativeWebView = nativeConfig.component; + + if (this.props.useWebKit) { + NativeWebView = NativeWebView || RCTWKWebView; + } else { + NativeWebView = NativeWebView || RCTWebView; + } const webView = ( { UIManager.dispatchViewManagerCommand( this.getWebViewHandle(), - UIManager.RCTWebView.Commands.goForward, + this._getCommands().goForward, null, ); }; @@ -531,7 +566,7 @@ class WebView extends React.Component { goBack = () => { UIManager.dispatchViewManagerCommand( this.getWebViewHandle(), - UIManager.RCTWebView.Commands.goBack, + this._getCommands().goBack, null, ); }; @@ -543,7 +578,7 @@ class WebView extends React.Component { this.setState({viewState: WebViewState.LOADING}); UIManager.dispatchViewManagerCommand( this.getWebViewHandle(), - UIManager.RCTWebView.Commands.reload, + this._getCommands().reload, null, ); }; @@ -554,7 +589,7 @@ class WebView extends React.Component { stopLoading = () => { UIManager.dispatchViewManagerCommand( this.getWebViewHandle(), - UIManager.RCTWebView.Commands.stopLoading, + this._getCommands().stopLoading, null, ); }; @@ -572,7 +607,7 @@ class WebView extends React.Component { postMessage = data => { UIManager.dispatchViewManagerCommand( this.getWebViewHandle(), - UIManager.RCTWebView.Commands.postMessage, + this._getCommands().postMessage, [String(data)], ); }; @@ -586,7 +621,7 @@ class WebView extends React.Component { injectJavaScript = data => { UIManager.dispatchViewManagerCommand( this.getWebViewHandle(), - UIManager.RCTWebView.Commands.injectJavaScript, + this._getCommands().injectJavaScript, [data], ); }; @@ -641,9 +676,36 @@ class WebView extends React.Component { const {onMessage} = this.props; onMessage && onMessage(event); }; + + componentDidUpdate(prevProps) { + if (!(prevProps.useWebKit && this.props.useWebKit)) { + return; + } + + this._showRedboxOnPropChanges(prevProps, 'allowsInlineMediaPlayback'); + this._showRedboxOnPropChanges(prevProps, 'mediaPlaybackRequiresUserAction'); + this._showRedboxOnPropChanges(prevProps, 'dataDetectorTypes'); + } + + _showRedboxOnPropChanges(prevProps, propName: string) { + if (this.props[propName] !== prevProps[propName]) { + console.error( + `Changes to property ${propName} do nothing after the initial render.`, + ); + } + } } -const RCTWebView = requireNativeComponent('RCTWebView'); +const RCTWebView = requireNativeComponent( + 'RCTWebView', + WebView, + WebView.extraNativeComponentConfig, +); +const RCTWKWebView = requireNativeComponent( + 'RCTWKWebView', + WebView, + WebView.extraNativeComponentConfig, +); const styles = StyleSheet.create({ container: { From 262d286f4b48a962e99d2c0b993b3336f4c9382a Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 16 Aug 2018 13:34:31 -0700 Subject: [PATCH 070/273] Warn when 'scalesPageToFit' prop is used Summary: @public The `WKWebView` class doesn't expose a `scalesPageToFit` property, unlike `UIWebView`. Therefore, the `scalesPageToFit` RN prop is be a bit tricky to implement with `WKWebView`. For the time being, this diff adds warnings to `` whenever `useWebKit={true}` and `scalesPageToFit` is set. I've also updated the documentation to reflect that we don't support `scalesPageToFit` prop with the new implementation of ``. Reviewed By: shergin Differential Revision: D6429271 fbshipit-source-id: adf858cb67ba221c70d6d6f1bd6cff505e90c365 --- Libraries/Components/WebView/WebView.ios.js | 28 +++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/Libraries/Components/WebView/WebView.ios.js b/Libraries/Components/WebView/WebView.ios.js index f158addaaefdbe..329dd2027c1844 100644 --- a/Libraries/Components/WebView/WebView.ios.js +++ b/Libraries/Components/WebView/WebView.ios.js @@ -324,6 +324,8 @@ class WebView extends React.Component { * Boolean that controls whether the web content is scaled to fit * the view and enables the user to change the scale. The default value * is `true`. + * + * On iOS, when `useWebKit=true`, this prop will not work. */ scalesPageToFit: PropTypes.bool, @@ -403,7 +405,6 @@ class WebView extends React.Component { static defaultProps = { originWhitelist: WebViewShared.defaultOriginWhitelist, - scalesPageToFit: true, }; state = { @@ -416,11 +417,28 @@ class WebView extends React.Component { if (this.props.startInLoadingState) { this.setState({viewState: WebViewState.LOADING}); } + + if ( + this.props.useWebKit === true && + this.props.scalesPageToFit !== undefined + ) { + console.warn( + 'The scalesPageToFit property is not supported when useWebKit = true', + ); + } } render() { let otherView = null; + let scalesPageToFit; + + if (this.props.useWebKit) { + ({scalesPageToFit} = this.props); + } else { + ({scalesPageToFit = true} = this.props); + } + if (this.state.viewState === WebViewState.LOADING) { otherView = (this.props.renderLoading || defaultRenderLoading)(); } else if (this.state.viewState === WebViewState.ERROR) { @@ -523,7 +541,7 @@ class WebView extends React.Component { messagingEnabled={messagingEnabled} onMessage={this._onMessage} onShouldStartLoadWithRequest={onShouldStartLoadWithRequest} - scalesPageToFit={this.props.scalesPageToFit} + scalesPageToFit={scalesPageToFit} allowsInlineMediaPlayback={this.props.allowsInlineMediaPlayback} mediaPlaybackRequiresUserAction={ this.props.mediaPlaybackRequiresUserAction @@ -685,6 +703,12 @@ class WebView extends React.Component { this._showRedboxOnPropChanges(prevProps, 'allowsInlineMediaPlayback'); this._showRedboxOnPropChanges(prevProps, 'mediaPlaybackRequiresUserAction'); this._showRedboxOnPropChanges(prevProps, 'dataDetectorTypes'); + + if (this.props.scalesPageToFit !== undefined) { + console.warn( + 'The scalesPageToFit property is not supported when useWebKit = true', + ); + } } _showRedboxOnPropChanges(prevProps, propName: string) { From 959aacff73783db83240c44266ea929aec6a018b Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 16 Aug 2018 13:34:33 -0700 Subject: [PATCH 071/273] Dynamically load WebKit Summary: @public We can't dynamically link `WebKit` because doing so will impact cold start of all our Apps. This diff includes a few changes: 1. Weakly link the `WebKit` framework in the `ReactInternal` library, so that the compiler doesn't die when it encounters a WebKit symbol. 2. Undo dynamic linking of WebKit in Catalyst. 3. Undo dynamic linking of WebKit in AdsManager 4. Before the first `WKWebView` is instantiated, dynamically load the `WebKit` framework. The end result of these changes is that WebKit will be loaded only when it's going to be used. Reviewed By: mmmulani Differential Revision: D6564328 fbshipit-source-id: a45a44e774d0c61c1fb578a6fa3d16bb08f68ac9 --- React/Base/RCTConvert.h | 3 +++ React/React.xcodeproj/project.pbxproj | 12 ++++++++++-- React/Views/RCTWKWebView.m | 23 +++++++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/React/Base/RCTConvert.h b/React/Base/RCTConvert.h index 1f66328ea76d18..dff41ec1328387 100644 --- a/React/Base/RCTConvert.h +++ b/React/Base/RCTConvert.h @@ -69,6 +69,9 @@ typedef NSURL RCTFileURL; + (UIReturnKeyType)UIReturnKeyType:(id)json; #if !TARGET_OS_TV + (UIDataDetectorTypes)UIDataDetectorTypes:(id)json; +#endif + +#if TARGET_OS_IPHONE + (WKDataDetectorTypes)WKDataDetectorTypes:(id)json; #endif diff --git a/React/React.xcodeproj/project.pbxproj b/React/React.xcodeproj/project.pbxproj index ac97a4d41e64a0..1f8c1e4b1ebea6 100644 --- a/React/React.xcodeproj/project.pbxproj +++ b/React/React.xcodeproj/project.pbxproj @@ -5240,7 +5240,11 @@ "RCT_METRO_PORT=${RCT_METRO_PORT}", ); GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - OTHER_LDFLAGS = "-ObjC"; + OTHER_LDFLAGS = ( + "-ObjC", + "-weak_framework", + WebKit, + ); PRODUCT_NAME = "$(TARGET_NAME)"; PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/React; RUN_CLANG_STATIC_ANALYZER = YES; @@ -5258,7 +5262,11 @@ "RCT_METRO_PORT=${RCT_METRO_PORT}", ); GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - OTHER_LDFLAGS = "-ObjC"; + OTHER_LDFLAGS = ( + "-ObjC", + "-weak_framework", + WebKit, + ); PRODUCT_NAME = "$(TARGET_NAME)"; PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/React; RUN_CLANG_STATIC_ANALYZER = NO; diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m index 2488ff209a9e78..71c2d88de905a2 100644 --- a/React/Views/RCTWKWebView.m +++ b/React/Views/RCTWKWebView.m @@ -23,6 +23,25 @@ - (void)dealloc } +/** + * See https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/DisplayWebContent/Tasks/WebKitAvail.html. + */ ++ (BOOL)dynamicallyLoadWebKitIfAvailable +{ + static BOOL _webkitAvailable=NO; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + NSBundle *webKitBundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/WebKit.framework"]; + if (webKitBundle) { + _webkitAvailable = [webKitBundle load]; + } + }); + + return _webkitAvailable; +} + + - (instancetype)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { @@ -38,6 +57,10 @@ - (instancetype)initWithFrame:(CGRect)frame - (void)didMoveToWindow { if (self.window != nil) { + if (![[self class] dynamicallyLoadWebKitIfAvailable]) { + return; + }; + WKWebViewConfiguration *wkWebViewConfig = [WKWebViewConfiguration new]; wkWebViewConfig.userContentController = [WKUserContentController new]; [wkWebViewConfig.userContentController addScriptMessageHandler: self name: MessageHanderName]; From e0df3a1a8b797d934d0fce5320d63cb6431e0db2 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Thu, 16 Aug 2018 13:34:35 -0700 Subject: [PATCH 072/273] Gate usage of WebKit 10.0 APIs Reviewed By: mmmulani Differential Revision: D9362001 fbshipit-source-id: 62cde6bcc1f190c168973b173ce55c029328bfbf --- React/Base/RCTConvert.h | 2 +- React/Base/RCTConvert.m | 5 ++++- React/Base/RCTDefines.h | 5 +++++ React/Views/RCTWKWebView.h | 3 +++ React/Views/RCTWKWebView.m | 4 +++- React/Views/RCTWKWebViewManager.m | 5 ++++- 6 files changed, 20 insertions(+), 4 deletions(-) diff --git a/React/Base/RCTConvert.h b/React/Base/RCTConvert.h index dff41ec1328387..ae2851f38da5a8 100644 --- a/React/Base/RCTConvert.h +++ b/React/Base/RCTConvert.h @@ -71,7 +71,7 @@ typedef NSURL RCTFileURL; + (UIDataDetectorTypes)UIDataDetectorTypes:(id)json; #endif -#if TARGET_OS_IPHONE +#if TARGET_OS_IPHONE && WEBKIT_IOS_10_APIS_AVAILABLE + (WKDataDetectorTypes)WKDataDetectorTypes:(id)json; #endif diff --git a/React/Base/RCTConvert.m b/React/Base/RCTConvert.m index 90335e9894a338..673cef70343c5f 100644 --- a/React/Base/RCTConvert.m +++ b/React/Base/RCTConvert.m @@ -362,6 +362,7 @@ + (NSLocale *)NSLocale:(id)json @"all": @(UIDataDetectorTypeAll), }), UIDataDetectorTypePhoneNumber, unsignedLongLongValue) +#if WEBKIT_IOS_10_APIS_AVAILABLE RCT_MULTI_ENUM_CONVERTER(WKDataDetectorTypes, (@{ @"phoneNumber": @(WKDataDetectorTypePhoneNumber), @"link": @(WKDataDetectorTypeLink), @@ -373,7 +374,9 @@ + (NSLocale *)NSLocale:(id)json @"none": @(WKDataDetectorTypeNone), @"all": @(WKDataDetectorTypeAll), }), WKDataDetectorTypePhoneNumber, unsignedLongLongValue) -#endif + #endif // WEBKIT_IOS_10_APIS_AVAILABLE + + #endif // !TARGET_OS_TV RCT_ENUM_CONVERTER(UIKeyboardAppearance, (@{ @"default": @(UIKeyboardAppearanceDefault), diff --git a/React/Base/RCTDefines.h b/React/Base/RCTDefines.h index 881af139d85c92..da0e918780fb73 100644 --- a/React/Base/RCTDefines.h +++ b/React/Base/RCTDefines.h @@ -125,3 +125,8 @@ _Pragma("clang diagnostic ignored \"-Wunused-parameter\"") \ RCT_EXTERN NSException *_RCTNotImplementedException(SEL, Class); \ method NS_UNAVAILABLE { @throw _RCTNotImplementedException(_cmd, [self class]); } \ _Pragma("clang diagnostic pop") + +/** + * Check if WebKit iOS 10.0 APIs are available. + */ +#define WEBKIT_IOS_10_APIS_AVAILABLE __has_include() diff --git a/React/Views/RCTWKWebView.h b/React/Views/RCTWKWebView.h index 62c1371085515e..e70a1cca1139b8 100644 --- a/React/Views/RCTWKWebView.h +++ b/React/Views/RCTWKWebView.h @@ -8,6 +8,7 @@ */ #import +#import #import @class RCTWKWebView; @@ -31,7 +32,9 @@ shouldStartLoadForRequest:(NSMutableDictionary *)request @property (nonatomic, assign) BOOL allowsInlineMediaPlayback; @property (nonatomic, assign) BOOL bounces; @property (nonatomic, assign) BOOL mediaPlaybackRequiresUserAction; +#if WEBKIT_IOS_10_APIS_AVAILABLE @property (nonatomic, assign) WKDataDetectorTypes dataDetectorTypes; +#endif @property (nonatomic, assign) UIEdgeInsets contentInset; @property (nonatomic, assign) BOOL automaticallyAdjustContentInsets; diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m index 71c2d88de905a2..02a66c1ccaf33a 100644 --- a/React/Views/RCTWKWebView.m +++ b/React/Views/RCTWKWebView.m @@ -65,10 +65,12 @@ - (void)didMoveToWindow wkWebViewConfig.userContentController = [WKUserContentController new]; [wkWebViewConfig.userContentController addScriptMessageHandler: self name: MessageHanderName]; wkWebViewConfig.allowsInlineMediaPlayback = _allowsInlineMediaPlayback; +#if WEBKIT_IOS_10_APIS_AVAILABLE wkWebViewConfig.mediaTypesRequiringUserActionForPlayback = _mediaPlaybackRequiresUserAction ? WKAudiovisualMediaTypeAll : WKAudiovisualMediaTypeNone; - wkWebViewConfig.dataDetectorTypes = _dataDetectorTypes; + wkWebViewConfig.dataDetectorTypes = _dataDetectorTypes; +#endif _webView = [[WKWebView alloc] initWithFrame:self.bounds configuration: wkWebViewConfig]; _webView.scrollView.delegate = self; diff --git a/React/Views/RCTWKWebViewManager.m b/React/Views/RCTWKWebViewManager.m index f0380185510285..31e2655e114593 100644 --- a/React/Views/RCTWKWebViewManager.m +++ b/React/Views/RCTWKWebViewManager.m @@ -2,6 +2,7 @@ #import "RCTUIManager.h" #import "RCTWKWebView.h" +#import @interface RCTWKWebViewManager () @end @@ -29,10 +30,12 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(injectedJavaScript, NSString) RCT_EXPORT_VIEW_PROPERTY(allowsInlineMediaPlayback, BOOL) RCT_EXPORT_VIEW_PROPERTY(mediaPlaybackRequiresUserAction, BOOL) +#if WEBKIT_IOS_10_APIS_AVAILABLE RCT_EXPORT_VIEW_PROPERTY(dataDetectorTypes, WKDataDetectorTypes) +#endif RCT_EXPORT_VIEW_PROPERTY(contentInset, UIEdgeInsets) RCT_EXPORT_VIEW_PROPERTY(automaticallyAdjustContentInsets, BOOL) - + /** * Expose methods to enable messaging the webview. */ From 126e4c655924fc26cf9d9d34223f0e58edc0fb19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Thu, 16 Aug 2018 17:25:06 -0700 Subject: [PATCH 073/273] Fix Flow errors (#20696) Summary: Revert change to flow strict-local in OSS. Pull Request resolved: https://github.com/facebook/react-native/pull/20696 Differential Revision: D9367630 Pulled By: hramos fbshipit-source-id: 17e4d1ab6d00b2e14033b223d878d5fcd1c098f4 --- local-cli/bundle/types.flow.js | 2 +- local-cli/server/server.js | 2 +- local-cli/templates/HelloWorld/App.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/local-cli/bundle/types.flow.js b/local-cli/bundle/types.flow.js index 6fbd570daf6eb3..3fb3d930ee1bbb 100644 --- a/local-cli/bundle/types.flow.js +++ b/local-cli/bundle/types.flow.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict-local + * @flow */ 'use strict'; diff --git a/local-cli/server/server.js b/local-cli/server/server.js index 5862af217b72e6..4865cbcc7a6920 100644 --- a/local-cli/server/server.js +++ b/local-cli/server/server.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict-local + * @flow */ 'use strict'; diff --git a/local-cli/templates/HelloWorld/App.js b/local-cli/templates/HelloWorld/App.js index db41976f413c26..171d0f0f4a8532 100644 --- a/local-cli/templates/HelloWorld/App.js +++ b/local-cli/templates/HelloWorld/App.js @@ -3,7 +3,7 @@ * https://github.com/facebook/react-native * * @format - * @flow strict-local + * @flow */ import React, {Component} from 'react'; From b44449395c25fc01745482477df91b677af73564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Thu, 16 Aug 2018 18:34:52 -0700 Subject: [PATCH 074/273] Fix old license that snuck into repo (#20702) Summary: Quick trivial PR to add back a necessary header. Fixes CI as well. Pull Request resolved: https://github.com/facebook/react-native/pull/20702 Differential Revision: D9374430 Pulled By: hramos fbshipit-source-id: dba0f1d4fc80e39242d8c3e6d1e0007492d2860d --- React/Views/RCTWKWebView.h | 6 ++---- React/Views/RCTWKWebView.m | 7 +++++++ React/Views/RCTWKWebViewManager.h | 7 ++++++- React/Views/RCTWKWebViewManager.m | 7 +++++++ 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/React/Views/RCTWKWebView.h b/React/Views/RCTWKWebView.h index e70a1cca1139b8..01b1f5e52aa922 100644 --- a/React/Views/RCTWKWebView.h +++ b/React/Views/RCTWKWebView.h @@ -1,10 +1,8 @@ /** * 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. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m index 02a66c1ccaf33a..16dc43a79a9fac 100644 --- a/React/Views/RCTWKWebView.m +++ b/React/Views/RCTWKWebView.m @@ -1,3 +1,10 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + #import "RCTWKWebView.h" #import #import "RCTAutoInsetsProtocol.h" diff --git a/React/Views/RCTWKWebViewManager.h b/React/Views/RCTWKWebViewManager.h index 9099e8cf3faf26..81145bea9fb143 100644 --- a/React/Views/RCTWKWebViewManager.h +++ b/React/Views/RCTWKWebViewManager.h @@ -1,4 +1,9 @@ -// Copyright 2004-present Facebook. All Rights Reserved. +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ #import diff --git a/React/Views/RCTWKWebViewManager.m b/React/Views/RCTWKWebViewManager.m index 31e2655e114593..cd56b66b0e29d2 100644 --- a/React/Views/RCTWKWebViewManager.m +++ b/React/Views/RCTWKWebViewManager.m @@ -1,3 +1,10 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + #import "RCTWKWebViewManager.h" #import "RCTUIManager.h" From e4f4c31236fe06a37616273962eacf19fdd812a1 Mon Sep 17 00:00:00 2001 From: Nick Graef Date: Wed, 22 Aug 2018 10:39:11 -0700 Subject: [PATCH 075/273] ignore babelrc in git-upgrade (#20790) Summary: Per [this comment on the issue](https://github.com/facebook/react-native/issues/20710#issuecomment-414631827): > Babel by default tries to find .babelrc files to configure itself, and once it finds the one from the RN app (which links to the RN preset that only works on Babel 7) it fails. > The easiest patch to fix this issue is to add babelrc: false to the babel-register method, so Babel does not read any additional .babelrc file. Fixes #20710 Pull Request resolved: https://github.com/facebook/react-native/pull/20790 Differential Revision: D9458502 Pulled By: hramos fbshipit-source-id: 3a0ed7261322fdd9e0c0840f8a3944974f38b233 --- react-native-git-upgrade/cli.js | 1 + 1 file changed, 1 insertion(+) diff --git a/react-native-git-upgrade/cli.js b/react-native-git-upgrade/cli.js index 19103c9fefb9df..d54cf4a26beed6 100644 --- a/react-native-git-upgrade/cli.js +++ b/react-native-git-upgrade/cli.js @@ -10,6 +10,7 @@ 'use strict'; require('babel-register')({ + babelrc: false, presets: [ require('babel-preset-es2015-node'), require('babel-preset-stage-3'), From d0c6ccb739f3b6742ec41b9a03275a660cf4297d Mon Sep 17 00:00:00 2001 From: jamsch Date: Mon, 20 Aug 2018 14:47:49 -0700 Subject: [PATCH 076/273] Add missing "--terminal" argument to run-android (#20584) Summary: Commit 79e498b7fbf19ab50bb73697602910fb827ff928 claims that "--terminal" has been added as an argument to the "run-android" script which it hasn't. Instead it adds a new environment variable "process.env.REACT_TERMINAL" which seems to be undocumented and nowhere else in the repository. This commit now allows Linux and OSX users to specify their custom terminal : react-native run-android --terminal=x-terminal-emulator Additionally the metro bundler child process "detached" option has been set to false if no terminal has been specified on Linux which fixes an issue where the packager would be running in the background and would have to manually be closed by finding the process. Fixes #18122 Pull Request resolved: https://github.com/facebook/react-native/pull/20584 Differential Revision: D9234990 Pulled By: hramos fbshipit-source-id: 60e4cc57b2790c419d5a4f9027add04313ddf6f8 --- local-cli/runAndroid/runAndroid.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/local-cli/runAndroid/runAndroid.js b/local-cli/runAndroid/runAndroid.js index 6835c97bcb0bf0..2bb7dd7446f262 100644 --- a/local-cli/runAndroid/runAndroid.js +++ b/local-cli/runAndroid/runAndroid.js @@ -60,7 +60,7 @@ function runAndroid(argv, config, args) { } else { // result == 'not_running' console.log(chalk.bold('Starting JS server...')); - startServerInNewWindow(args.port); + startServerInNewWindow(args.port, args.terminal); } return buildAndRun(args); }); @@ -348,7 +348,7 @@ function runOnAllDevices( } } -function startServerInNewWindow(port) { +function startServerInNewWindow(port, terminal = process.env.REACT_TERMINAL) { // set up OS-specific filenames and commands const isWindows = /^win/.test(process.platform); const scriptFile = isWindows @@ -363,7 +363,6 @@ function startServerInNewWindow(port) { const scriptsDir = path.resolve(__dirname, '..', '..', 'scripts'); const launchPackagerScript = path.resolve(scriptsDir, scriptFile); const procConfig = {cwd: scriptsDir}; - const terminal = process.env.REACT_TERMINAL; // set up the .packager.(env|bat) file to ensure the packager starts on the right port const packagerEnvFile = path.join( @@ -390,14 +389,16 @@ function startServerInNewWindow(port) { } return child_process.spawnSync('open', [launchPackagerScript], procConfig); } else if (process.platform === 'linux') { - procConfig.detached = true; if (terminal) { + procConfig.detached = true; return child_process.spawn( terminal, ['-e', 'sh ' + launchPackagerScript], procConfig, ); } + // By default, the child shell process will be attached to the parent + procConfig.detached = false; return child_process.spawn('sh', [launchPackagerScript], procConfig); } else if (/^win/.test(process.platform)) { procConfig.detached = true; @@ -474,5 +475,11 @@ module.exports = { default: process.env.RCT_METRO_PORT || 8081, parse: (val: string) => Number(val), }, + { + command: '--terminal [string]', + description: + 'Launches the Metro Bundler in a new window using the specified terminal path.', + default: '', + }, ], }; From 8cd5be67ffc9ae333b0af687ea75dbbd5d013be5 Mon Sep 17 00:00:00 2001 From: Hector Ramos Date: Wed, 22 Aug 2018 12:54:21 -0700 Subject: [PATCH 077/273] [0.57.0-rc.1] Bump version numbers --- Libraries/Core/ReactNativeVersion.js | 2 +- React/Base/RCTVersion.m | 2 +- ReactAndroid/gradle.properties | 2 +- .../facebook/react/modules/systeminfo/ReactNativeVersion.java | 2 +- package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Libraries/Core/ReactNativeVersion.js b/Libraries/Core/ReactNativeVersion.js index 3c3a2232cbea18..ab20d61f49584b 100644 --- a/Libraries/Core/ReactNativeVersion.js +++ b/Libraries/Core/ReactNativeVersion.js @@ -13,5 +13,5 @@ exports.version = { major: 0, minor: 57, patch: 0, - prerelease: 'rc.0', + prerelease: 'rc.1', }; diff --git a/React/Base/RCTVersion.m b/React/Base/RCTVersion.m index 6934e6619d9cb6..f5e33282d927cd 100644 --- a/React/Base/RCTVersion.m +++ b/React/Base/RCTVersion.m @@ -23,7 +23,7 @@ static void __makeVersion() RCTVersionMajor: @(0), RCTVersionMinor: @(57), RCTVersionPatch: @(0), - RCTVersionPrerelease: @"rc.0", + RCTVersionPrerelease: @"rc.1", }; } diff --git a/ReactAndroid/gradle.properties b/ReactAndroid/gradle.properties index a42263b074e880..5f2f3465699d86 100644 --- a/ReactAndroid/gradle.properties +++ b/ReactAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=0.57.0-rc.0 +VERSION_NAME=0.57.0-rc.1 GROUP=com.facebook.react POM_NAME=ReactNative diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java index 7441b9e17cd2db..40acd764794ccc 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java @@ -18,5 +18,5 @@ public class ReactNativeVersion { "major", 0, "minor", 57, "patch", 0, - "prerelease", "rc.0"); + "prerelease", "rc.1"); } diff --git a/package.json b/package.json index 19f07c6ce10125..67ca7374fa7317 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native", - "version": "0.57.0-rc.0", + "version": "0.57.0-rc.1", "description": "A framework for building native apps using React", "license": "MIT", "repository": { From 56e5884f86331fccc9597cfa8072385a721dab27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Mon, 20 Aug 2018 14:33:18 -0700 Subject: [PATCH 078/273] Disable Podspec tests Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/20755 Differential Revision: D9408317 Pulled By: hramos fbshipit-source-id: 7799cf8ee4c99662299ef9cf1a26913cdf0d8b39 --- .circleci/config.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 212ac52a705f5f..26a713b185cabf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -436,7 +436,8 @@ jobs: # Runs unit tests on iOS and Apple TV devices test_objc: <<: *macos_defaults - parallelism: 3 + # Bump back to 3 whenever podspec tests are re-enabled + parallelism: 2 steps: - attach_workspace: at: ~/react-native @@ -447,7 +448,8 @@ jobs: - run: *run-objc-ios-tests-with-parallelism - run: *run-objc-tvos-tests-with-parallelism - - run: *run-podspec-tests-with-parallelism + # Disabled + # - run: *run-podspec-tests-with-parallelism - store_test_results: path: ~/react-native/reports/junit From d286ff923a70a4e04e19d4d41ee1dca3ffc56699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= <165856+hramos@users.noreply.github.com> Date: Mon, 20 Aug 2018 17:31:59 -0700 Subject: [PATCH 079/273] WIP: Add Node 10 job to workflow Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/19299 Differential Revision: D9413583 Pulled By: hramos fbshipit-source-id: 61ac48e46feaba5f1ec80362b5e1c7f2787ee167 --- .circleci/config.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 26a713b185cabf..50f4a5f4b9a21d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -433,6 +433,21 @@ jobs: - store_test_results: path: ~/react-native/reports/junit + # Run JavaScript tests on Node 10 + test_node10: + <<: *defaults + docker: + - image: circleci/node:10 + environment: + - PATH: "/opt/yarn/yarn-v1.5.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + steps: + - checkout + - run: *setup-artifacts + - run: *yarn + - run: *run-js-tests + - store_test_results: + path: ~/react-native/reports/junit + # Runs unit tests on iOS and Apple TV devices test_objc: <<: *macos_defaults @@ -665,6 +680,10 @@ workflows: requires: - checkout_code + # Test JavaScript and Node 10 compatibility + - test_node10: + filters: *filter-ignore-gh-pages + # Test Android - test_android: filters: *filter-ignore-gh-pages From aa6af734a389d44b1c34fa07f48ab21a4e9ac309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Tue, 21 Aug 2018 20:16:41 -0700 Subject: [PATCH 080/273] Run failing tests in CI, without turning CI red (#20775) Summary: We have several disabled tests in Circle, and they are not running at all. This prevents us from seeing when a disabled test might actually be fixed, as enabling the test requires uncommenting the correct line in Circle CI's config. In this PR, we use the existing swallow_error script to run known-failing steps, without failing the job. This will let us see the step's output in CI, without polluting PRs that have not introduced new failures to CI. Pull Request resolved: https://github.com/facebook/react-native/pull/20775 Differential Revision: D9442412 Pulled By: hramos fbshipit-source-id: 83c930811a559fdcf6d7b926b4073343e862d2b3 --- .circleci/config.yml | 172 ++++++++++--------------- scripts/circleci/exec_swallow_error.sh | 7 +- 2 files changed, 71 insertions(+), 108 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 50f4a5f4b9a21d..e7bfb892a6dd5e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -275,81 +275,45 @@ aliases: name: Boot iPhone Simulator command: xcrun simctl boot "iPhone 5s" || true - - &boot-simulator-iphone-with-parallelism - name: Boot iPhone Simulator - command: | - if [ $((0 % CIRCLE_NODE_TOTAL)) -eq "$CIRCLE_NODE_INDEX" ]; then - xcrun simctl boot "iPhone 5s" || true - fi - - - &boot-simulator-appletv-with-parallelism + - &boot-simulator-appletv name: Boot Apple TV Simulator - command: | - if [ $((1 % CIRCLE_NODE_TOTAL)) -eq "$CIRCLE_NODE_INDEX" ]; then - xcrun simctl boot "Apple TV" || true - fi + command: xcrun simctl boot "Apple TV" || true - - &run-objc-ios-tests-with-parallelism + - &run-objc-ios-tests name: iOS Test Suite - command: | - if [ $((0 % CIRCLE_NODE_TOTAL)) -eq "$CIRCLE_NODE_INDEX" ]; then - ./scripts/objc-test-ios.sh test - fi + command: ./scripts/objc-test-ios.sh test - - &run-objc-tvos-tests-with-parallelism + - &run-objc-tvos-tests name: tvOS Test Suite - command: | - if [ $((1 % CIRCLE_NODE_TOTAL)) -eq "$CIRCLE_NODE_INDEX" ]; then - ./scripts/objc-test-tvos.sh test - fi + command: ./scripts/objc-test-tvos.sh test - - &run-podspec-tests-with-parallelism - name: Test CocoaPods + - &run-podspec-tests + name: Test CocoaPods (Ignoring failures) command: | - if [ $((2 % CIRCLE_NODE_TOTAL)) -eq "$CIRCLE_NODE_INDEX" ]; then - ./scripts/process-podspecs.sh - fi + echo 'The following step is known to be failing in master, and any failures will be ignored.' + scripts/circleci/exec_swallow_error.sh ./scripts/process-podspecs.sh - &run-e2e-tests name: End-to-End Test Suite command: node ./scripts/run-ci-e2e-tests.js --android --ios --tvos --js --retries 3; - - &install-node-8 - name: Install Node 8 - command: | - echo 'export PATH=/usr/local/opt/node@8/bin:$PATH' >> $BASH_ENV - source $BASH_ENV - brew install node@8 - brew link node@8 - node -v - - - &install-apple-simulator-utils - name: Install Apple Simulator Utilities - command: | - brew tap wix/brew - brew install applesimutils - - - &build-ios-app-e2e - name: Build iOS App for Simulator - command: yarn run build-ios-e2e - - - &run-ios-detox-tests - name: Run Detox Tests - command: yarn run test-ios-e2e - - &run-objc-ios-e2e-tests - name: iOS End-to-End Test Suite + name: iOS End-to-End Test Suite (Ignoring failures) command: | - node ./scripts/run-ci-e2e-tests.js --ios --retries 3; + echo 'The following step is known to be failing in master, and any failures will be ignored.' + scripts/circleci/exec_swallow_error.sh node ./scripts/run-ci-e2e-tests.js --ios --retries 3; - &run-objc-tvos-e2e-tests - name: tvOS End-to-End Test Suite + name: tvOS End-to-End Test Suite (Ignoring failures) command: | - node ./scripts/run-ci-e2e-tests.js --tvos --js --retries 3; + echo 'The following step is known to be failing in master, and any failures will be ignored.' + scripts/circleci/exec_swallow_error.sh node ./scripts/run-ci-e2e-tests.js --tvos --js --retries 3; - &run-android-e2e-tests - name: Android End-to-End Test Suite - command: node ./scripts/run-ci-e2e-tests.js --android --retries 3; + name: Android End-to-End Test Suite (Ignoring failures) + command: | + echo 'The following step is known to be failing in master, and any failures will be ignored.' + scripts/circleci/exec_swallow_error.sh node ./scripts/run-ci-e2e-tests.js --android --retries 3; - &run-js-e2e-tests name: JavaScript End-to-End Test Suite @@ -451,56 +415,63 @@ jobs: # Runs unit tests on iOS and Apple TV devices test_objc: <<: *macos_defaults - # Bump back to 3 whenever podspec tests are re-enabled - parallelism: 2 steps: - attach_workspace: at: ~/react-native - - run: *boot-simulator-iphone-with-parallelism - - run: *boot-simulator-appletv-with-parallelism + - run: *boot-simulator-iphone + - run: *boot-simulator-appletv - run: *brew-install-watchman - - run: *run-objc-ios-tests-with-parallelism - - run: *run-objc-tvos-tests-with-parallelism - # Disabled - # - run: *run-podspec-tests-with-parallelism - - - store_test_results: - path: ~/react-native/reports/junit - - # Runs end to end tests (Objective-C) - test_objc_end_to_end: - <<: *macos_defaults - steps: - - attach_workspace: - at: ~/react-native - - - run: *boot-simulator-iphone + - run: *run-objc-ios-tests + - run: *run-objc-tvos-tests + # The following are "disabled" - the steps will + # still run, but failures will be ignored. + # This is good for debugging flaky CI steps. + # TODO: Reenable as soon as they are in working order. + - run: *run-podspec-tests - run: *run-objc-ios-e2e-tests + - run: *run-objc-tvos-e2e-tests - store_test_results: path: ~/react-native/reports/junit # Runs end to end tests (Detox) - # Disabled. test_detox_end_to_end: <<: *macos_defaults steps: - attach_workspace: at: ~/react-native - - - run: *boot-simulator-iphone - - - run: *install-node-8 - - run: *install-apple-simulator-utils - - run: *build-ios-app-e2e - - - run: *run-ios-detox-tests - - - store_test_results: - path: ~/react-native/reports/junit + - run: xcrun simctl boot "iPhone 5s" || true + - run: + name: Configure Environment Variables + command: | + echo 'export PATH=/usr/local/opt/node@8/bin:$PATH' >> $BASH_ENV + source $BASH_ENV + - run: + name: Install Node 8 + command: | + brew install node@8 + brew link node@8 + brew tap wix/brew + brew install applesimutils + node -v + - run: *yarn + # The following are "disabled" - the steps will + # still run, but failures will be ignored. + # This is good for debugging flaky CI steps. + # TODO: Reenable as soon as they are in working order. + - run: + name: Build iOS app for simulator (Ignoring failures) + command: | + echo 'The following step is known to be failing in master, and any failures will be ignored.' + scripts/circleci/exec_swallow_error.sh yarn run build-ios-e2e + - run: + name: Run Detox Tests (Ignoring failures) + command: | + echo 'The following step is known to be failing in master, and any failures will be ignored.' + scripts/circleci/exec_swallow_error.sh yarn run test-ios-e2e # Set up an Android environment for downstream jobs test_android: @@ -565,8 +536,11 @@ jobs: - run: *build-android-rntester-app # Run Android end-to-end tests - # Disabled - # - run: *run-android-e2e-tests + # The following are "disabled" - the steps will + # still run, but failures will be ignored. + # This is good for debugging flaky CI steps. + # TODO: Reenable as soon as they are in working order. + - run: *run-android-e2e-tests # Collect Results - run: *collect-android-test-results @@ -696,19 +670,10 @@ workflows: requires: - checkout_code - # Disabled on master. - - # End-to-end tests - # - test_objc_end_to_end: - # filters: *filter-ignore-gh-pages - # requires: - # - checkout_code - - # - test_detox_end_to_end: - # filters: *filter-ignore-gh-pages - # requires: - # - checkout_code - + - test_detox_end_to_end: + filters: *filter-ignore-gh-pages + requires: + - checkout_code # Only runs on vX.X.X tags if all tests are green - publish_npm_package: @@ -722,7 +687,6 @@ workflows: - test_javascript - test_objc - test_android - # - test_objc_end_to_end # Only runs on PRs analyze: diff --git a/scripts/circleci/exec_swallow_error.sh b/scripts/circleci/exec_swallow_error.sh index 297cf5b01219d9..1c2470c7121354 100755 --- a/scripts/circleci/exec_swallow_error.sh +++ b/scripts/circleci/exec_swallow_error.sh @@ -1,13 +1,12 @@ #!/bin/bash # execute command -$@ +"$@" # check status STATUS=$? if [ $STATUS == 0 ]; then - echo "Command '$@' completed successfully" + echo "Command " "$@" " completed successfully" else - echo "Command '$@' exited with error status $STATUS" + echo "Command " "$@" " exited with error status $STATUS" fi - From 2739bf45ccf0ab075bd64c609297c26f9e09b844 Mon Sep 17 00:00:00 2001 From: Hector Ramos Date: Wed, 22 Aug 2018 13:19:59 -0700 Subject: [PATCH 081/273] Revert "[0.57.0-rc.1] Bump version numbers" This reverts commit 8cd5be67ffc9ae333b0af687ea75dbbd5d013be5. --- Libraries/Core/ReactNativeVersion.js | 2 +- React/Base/RCTVersion.m | 2 +- ReactAndroid/gradle.properties | 2 +- .../facebook/react/modules/systeminfo/ReactNativeVersion.java | 2 +- package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Libraries/Core/ReactNativeVersion.js b/Libraries/Core/ReactNativeVersion.js index ab20d61f49584b..3c3a2232cbea18 100644 --- a/Libraries/Core/ReactNativeVersion.js +++ b/Libraries/Core/ReactNativeVersion.js @@ -13,5 +13,5 @@ exports.version = { major: 0, minor: 57, patch: 0, - prerelease: 'rc.1', + prerelease: 'rc.0', }; diff --git a/React/Base/RCTVersion.m b/React/Base/RCTVersion.m index f5e33282d927cd..6934e6619d9cb6 100644 --- a/React/Base/RCTVersion.m +++ b/React/Base/RCTVersion.m @@ -23,7 +23,7 @@ static void __makeVersion() RCTVersionMajor: @(0), RCTVersionMinor: @(57), RCTVersionPatch: @(0), - RCTVersionPrerelease: @"rc.1", + RCTVersionPrerelease: @"rc.0", }; } diff --git a/ReactAndroid/gradle.properties b/ReactAndroid/gradle.properties index 5f2f3465699d86..a42263b074e880 100644 --- a/ReactAndroid/gradle.properties +++ b/ReactAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=0.57.0-rc.1 +VERSION_NAME=0.57.0-rc.0 GROUP=com.facebook.react POM_NAME=ReactNative diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java index 40acd764794ccc..7441b9e17cd2db 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java @@ -18,5 +18,5 @@ public class ReactNativeVersion { "major", 0, "minor", 57, "patch", 0, - "prerelease", "rc.1"); + "prerelease", "rc.0"); } diff --git a/package.json b/package.json index 67ca7374fa7317..19f07c6ce10125 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native", - "version": "0.57.0-rc.1", + "version": "0.57.0-rc.0", "description": "A framework for building native apps using React", "license": "MIT", "repository": { From a92bb3b06e57bcb0dd9378e098152ee429af425d Mon Sep 17 00:00:00 2001 From: Hector Ramos Date: Wed, 22 Aug 2018 13:20:20 -0700 Subject: [PATCH 082/273] [0.57.0-rc.1] Bump version numbers --- Libraries/Core/ReactNativeVersion.js | 2 +- React/Base/RCTVersion.m | 2 +- ReactAndroid/gradle.properties | 2 +- .../facebook/react/modules/systeminfo/ReactNativeVersion.java | 2 +- package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Libraries/Core/ReactNativeVersion.js b/Libraries/Core/ReactNativeVersion.js index 3c3a2232cbea18..ab20d61f49584b 100644 --- a/Libraries/Core/ReactNativeVersion.js +++ b/Libraries/Core/ReactNativeVersion.js @@ -13,5 +13,5 @@ exports.version = { major: 0, minor: 57, patch: 0, - prerelease: 'rc.0', + prerelease: 'rc.1', }; diff --git a/React/Base/RCTVersion.m b/React/Base/RCTVersion.m index 6934e6619d9cb6..f5e33282d927cd 100644 --- a/React/Base/RCTVersion.m +++ b/React/Base/RCTVersion.m @@ -23,7 +23,7 @@ static void __makeVersion() RCTVersionMajor: @(0), RCTVersionMinor: @(57), RCTVersionPatch: @(0), - RCTVersionPrerelease: @"rc.0", + RCTVersionPrerelease: @"rc.1", }; } diff --git a/ReactAndroid/gradle.properties b/ReactAndroid/gradle.properties index a42263b074e880..5f2f3465699d86 100644 --- a/ReactAndroid/gradle.properties +++ b/ReactAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=0.57.0-rc.0 +VERSION_NAME=0.57.0-rc.1 GROUP=com.facebook.react POM_NAME=ReactNative diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java index 7441b9e17cd2db..40acd764794ccc 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java @@ -18,5 +18,5 @@ public class ReactNativeVersion { "major", 0, "minor", 57, "patch", 0, - "prerelease", "rc.0"); + "prerelease", "rc.1"); } diff --git a/package.json b/package.json index 19f07c6ce10125..67ca7374fa7317 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native", - "version": "0.57.0-rc.0", + "version": "0.57.0-rc.1", "description": "A framework for building native apps using React", "license": "MIT", "repository": { From f7fc381eda7750b7f14b6cbcc8533cf1c30e7597 Mon Sep 17 00:00:00 2001 From: Hector Ramos Date: Wed, 22 Aug 2018 14:55:35 -0700 Subject: [PATCH 083/273] [0.57.0-rc.2] Bump version numbers --- Libraries/Core/ReactNativeVersion.js | 2 +- React/Base/RCTVersion.m | 2 +- ReactAndroid/gradle.properties | 2 +- .../facebook/react/modules/systeminfo/ReactNativeVersion.java | 2 +- package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Libraries/Core/ReactNativeVersion.js b/Libraries/Core/ReactNativeVersion.js index ab20d61f49584b..478af88a7ba392 100644 --- a/Libraries/Core/ReactNativeVersion.js +++ b/Libraries/Core/ReactNativeVersion.js @@ -13,5 +13,5 @@ exports.version = { major: 0, minor: 57, patch: 0, - prerelease: 'rc.1', + prerelease: 'rc.2', }; diff --git a/React/Base/RCTVersion.m b/React/Base/RCTVersion.m index f5e33282d927cd..8ec15ca95b0912 100644 --- a/React/Base/RCTVersion.m +++ b/React/Base/RCTVersion.m @@ -23,7 +23,7 @@ static void __makeVersion() RCTVersionMajor: @(0), RCTVersionMinor: @(57), RCTVersionPatch: @(0), - RCTVersionPrerelease: @"rc.1", + RCTVersionPrerelease: @"rc.2", }; } diff --git a/ReactAndroid/gradle.properties b/ReactAndroid/gradle.properties index 5f2f3465699d86..838998a6dfe62c 100644 --- a/ReactAndroid/gradle.properties +++ b/ReactAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=0.57.0-rc.1 +VERSION_NAME=0.57.0-rc.2 GROUP=com.facebook.react POM_NAME=ReactNative diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java index 40acd764794ccc..f5f8abf41d6d77 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java @@ -18,5 +18,5 @@ public class ReactNativeVersion { "major", 0, "minor", 57, "patch", 0, - "prerelease", "rc.1"); + "prerelease", "rc.2"); } diff --git a/package.json b/package.json index 67ca7374fa7317..1c9e8f9171714e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native", - "version": "0.57.0-rc.1", + "version": "0.57.0-rc.2", "description": "A framework for building native apps using React", "license": "MIT", "repository": { From 893c0274d6c071c5fa99dee097e189441af74148 Mon Sep 17 00:00:00 2001 From: Rafael Oleza Date: Wed, 22 Aug 2018 20:23:11 -0700 Subject: [PATCH 084/273] Fix default projectRoot + watchFolders computation Summary: @public This diff fixes the `projectRoot` calculation on React Native when the app does not have a config file. This should fix the issues reported in https://github.com/facebook/react-native/issues/20712 Reviewed By: hramos Differential Revision: D9444982 fbshipit-source-id: 4cb41fa5224d2addf92976cc119e49dea6a6346b --- local-cli/util/Config.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/local-cli/util/Config.js b/local-cli/util/Config.js index b55b061ec4cb37..d6d0134d133862 100644 --- a/local-cli/util/Config.js +++ b/local-cli/util/Config.js @@ -21,7 +21,7 @@ const {loadConfig} = require('metro-config'); */ import type {ConfigT} from 'metro-config/src/configTypes.flow'; -function getProjectPath() { +function getProjectRoot() { if ( __dirname.match(/node_modules[\/\\]react-native[\/\\]local-cli[\/\\]util$/) ) { @@ -44,12 +44,12 @@ const resolveSymlinksForRoots = roots => [...roots], ); -const getProjectRoots = () => { +const getWatchFolders = () => { const root = process.env.REACT_NATIVE_APP_ROOT; if (root) { return resolveSymlinksForRoots([path.resolve(root)]); } - return resolveSymlinksForRoots([getProjectPath()]); + return []; }; const getBlacklistRE = () => { @@ -76,17 +76,15 @@ const Config = { ], getPolyfills, }, - - watchFolders: [getProjectPath(), ...getProjectRoots()], + watchFolders: getWatchFolders(), transformModulePath: require.resolve('metro/src/reactNativeTransformer'), }, - getProjectPath, - getProjectRoots, - async load(configFile: ?string): Promise { + const argv = {cwd: getProjectRoot()}; + return await loadConfig( - configFile ? {config: configFile} : {}, + configFile ? {...argv, config: configFile} : argv, this.DEFAULT, ); }, From 9a4c21f92bf7a979d1719dd9dad533fb246786ca Mon Sep 17 00:00:00 2001 From: Elias Toivanen Date: Wed, 22 Aug 2018 20:23:43 -0700 Subject: [PATCH 085/273] Bugfix: Check NodeJS version successfully even for old runtimes (Fixes #20769) (#20779) Summary: Fixes #20769 Release notes -------------- [CLI] [BUGFIX] [local-cli/server/checkNodeVersion.js] - Disable auto-formatting in `local-cli/server/checkNodeVersion.js` since it introduces ES6 and ES7 syntax (trailing comma in argument list) which in turn makes ES5 engines crash with a `SyntaxError`. Pull Request resolved: https://github.com/facebook/react-native/pull/20779 Differential Revision: D9468346 Pulled By: hramos fbshipit-source-id: 24761a377a5fd104e11ed6b6e86da15e96a0e38b --- local-cli/server/checkNodeVersion.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/local-cli/server/checkNodeVersion.js b/local-cli/server/checkNodeVersion.js index cfc17dcf2d2293..9fd026f17c388a 100644 --- a/local-cli/server/checkNodeVersion.js +++ b/local-cli/server/checkNodeVersion.js @@ -4,7 +4,10 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @format + * Be mindful that this script may be run by legacy NodeJS runtimes. Keep this + * script ES5 compatible (e.g. do not insert the `@format` pragma here which + * may introduce non-ES5 compatible syntax.) + * */ 'use strict'; @@ -36,7 +39,7 @@ module.exports = function() { marginLeft: 1, marginRight: 1, paddingBottom: 1, - }), + }) ); process.exit(1); } From 7a246e4872ec29a521216877ae5f5d26b5384a38 Mon Sep 17 00:00:00 2001 From: Sergei Dryganets Date: Wed, 22 Aug 2018 23:00:07 -0700 Subject: [PATCH 086/273] Android. OkHttp crash fixed on upload re-try. (#20802) Summary: This change fixes this issue: https://github.com/facebook/react-native/issues/10423 Pull Request resolved: https://github.com/facebook/react-native/pull/20802 Differential Revision: D9478422 Pulled By: hramos fbshipit-source-id: ce3a098a71c8f50a62b011a2a277004ab7a7b655 --- .../react/modules/network/ProgressRequestBody.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/ProgressRequestBody.java b/ReactAndroid/src/main/java/com/facebook/react/modules/network/ProgressRequestBody.java index 914ce3c901106a..3094732afea37a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/network/ProgressRequestBody.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/ProgressRequestBody.java @@ -19,7 +19,6 @@ public class ProgressRequestBody extends RequestBody { private final RequestBody mRequestBody; private final ProgressListener mProgressListener; - private BufferedSink mBufferedSink; private long mContentLength = 0L; public ProgressRequestBody(RequestBody requestBody, ProgressListener progressListener) { @@ -42,16 +41,17 @@ public long contentLength() throws IOException { @Override public void writeTo(BufferedSink sink) throws IOException { - if (mBufferedSink == null) { - mBufferedSink = Okio.buffer(outputStreamSink(sink)); - } + // In 99% of cases, this method is called strictly once. + // The only case when it is called more than once is internal okhttp upload re-try. + // We need to re-create CountingOutputStream in this case as progress should be re-evaluated. + BufferedSink sinkWrapper = Okio.buffer(outputStreamSink(sink)); // contentLength changes for input streams, since we're using inputStream.available(), // so get the length before writing to the sink contentLength(); - mRequestBody.writeTo(mBufferedSink); - mBufferedSink.flush(); + mRequestBody.writeTo(sinkWrapper); + sinkWrapper.flush(); } private Sink outputStreamSink(BufferedSink sink) { From d9868f7ed8a47475c8cba24f8518b597db3d7724 Mon Sep 17 00:00:00 2001 From: Dulmandakh Date: Mon, 20 Aug 2018 17:56:43 -0700 Subject: [PATCH 087/273] Bump Android Support Library to 27.1.1 (#20586) Summary: This PR bumps Android Support Library version to 27.1.1. FYI, originally was a part of https://github.com/facebook/react-native/pull/20026. Pull Request resolved: https://github.com/facebook/react-native/pull/20586 Differential Revision: D9414901 Pulled By: hramos fbshipit-source-id: 580338e62a924c214accc5d944f17c81ad9e3f9f --- RNTester/android/app/build.gradle | 2 +- ReactAndroid/build.gradle | 2 +- ReactAndroid/libs/BUCK | 4 +- .../android/support-annotations/BUCK | 4 +- .../main/third-party/android/support/v4/BUCK | 44 ++++++++++++------- .../android/support/v7/appcompat-orig/BUCK | 4 +- .../link/__fixtures__/android/build.gradle | 2 +- .../__fixtures__/android/patchedBuild.gradle | 2 +- .../templates/HelloWorld/android/build.gradle | 2 +- 9 files changed, 39 insertions(+), 27 deletions(-) diff --git a/RNTester/android/app/build.gradle b/RNTester/android/app/build.gradle index 229e4c9952207a..f69c094c17660a 100644 --- a/RNTester/android/app/build.gradle +++ b/RNTester/android/app/build.gradle @@ -141,7 +141,7 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:26.1.0' + compile 'com.android.support:appcompat-v7:27.1.1' // Build React Native from source compile project(':ReactAndroid') diff --git a/ReactAndroid/build.gradle b/ReactAndroid/build.gradle index c98c5fb639102c..81c74385caa2e0 100644 --- a/ReactAndroid/build.gradle +++ b/ReactAndroid/build.gradle @@ -295,7 +295,7 @@ android { dependencies { compile fileTree(dir: 'src/main/third-party/java/infer-annotations/', include: ['*.jar']) compile 'javax.inject:javax.inject:1' - compile 'com.android.support:appcompat-v7:26.1.0' + compile 'com.android.support:appcompat-v7:27.1.1' compile 'com.facebook.fbui.textlayoutbuilder:textlayoutbuilder:1.0.0' compile "com.facebook.fresco:fresco:${FRESCO_VERSION}" compile "com.facebook.fresco:imagepipeline-okhttp3:${FRESCO_VERSION}" diff --git a/ReactAndroid/libs/BUCK b/ReactAndroid/libs/BUCK index 018a73b2d7cba1..9d188656453694 100644 --- a/ReactAndroid/libs/BUCK +++ b/ReactAndroid/libs/BUCK @@ -6,8 +6,8 @@ android_prebuilt_aar( remote_file( name = "appcompat-binary-aar", - sha1 = "da5771a9ac6e8f3a461360eed3c6f921dc7580fd", - url = "mvn:com.android.support:appcompat-v7:aar:26.1.0", + sha1 = "22b1ef4ff9ef1a3513c18eb132d597eac6ef1a86", + url = "mvn:com.android.support:appcompat-v7:aar:27.1.1", ) android_prebuilt_aar( diff --git a/ReactAndroid/src/main/third-party/android/support-annotations/BUCK b/ReactAndroid/src/main/third-party/android/support-annotations/BUCK index cad12896cee525..80a5ef65b053f4 100644 --- a/ReactAndroid/src/main/third-party/android/support-annotations/BUCK +++ b/ReactAndroid/src/main/third-party/android/support-annotations/BUCK @@ -6,6 +6,6 @@ prebuilt_jar( remote_file( name = "support-annotations-binary.jar", - sha1 = "0814258103cf26a15fcc26ecce35f5b7d24b73f8", - url = "mvn:com.android.support:support-annotations:jar:26.1.0", + sha1 = "39ded76b5e1ce1c5b2688e1d25cdc20ecee32007", + url = "mvn:com.android.support:support-annotations:jar:27.1.1", ) diff --git a/ReactAndroid/src/main/third-party/android/support/v4/BUCK b/ReactAndroid/src/main/third-party/android/support/v4/BUCK index e816510b9a807f..27aec407f2907b 100644 --- a/ReactAndroid/src/main/third-party/android/support/v4/BUCK +++ b/ReactAndroid/src/main/third-party/android/support/v4/BUCK @@ -5,6 +5,7 @@ android_library( ":android-lifecycle-common", ":android-lifecycle-core", ":android-lifecycle-runtime", + ":android-lifecycle-viewmodel", ":lib-support-v4-support-compat", ":lib-support-v4-support-core-ui", ":lib-support-v4-support-core-utils", @@ -28,6 +29,11 @@ android_prebuilt_aar( aar = ":android-lifecycle-runtime-aar", ) +android_prebuilt_aar( + name = "android-lifecycle-viewmodel", + aar = ":android-lifecycle-viewmodel-aar", +) + android_prebuilt_aar( name = "lib-support-v4-support-compat", aar = ":lib-support-v4-support-compat-aar", @@ -55,48 +61,54 @@ android_prebuilt_aar( remote_file( name = "android-lifecycle-runtime-aar", - sha1 = "30c60a8a357ee1321ffd0c9f08ef54b24045cd10", - url = "mvn:android.arch.lifecycle:runtime:aar:1.0.0", + sha1 = "95428e5f6bf6875a6a1125d2157c3836a1a837f5", + url = "mvn:android.arch.lifecycle:runtime:aar:1.1.0", ) remote_file( name = "android-lifecycle-common.jar", - sha1 = "e414a4cb28434e25c4f6aa71426eb20cf4874ae9", - url = "mvn:android.arch.lifecycle:common:jar:1.0.0", + sha1 = "0edf3f7bfb84a7521d0599efa3b0113a0ee90f85", + url = "mvn:android.arch.lifecycle:common:jar:1.1.0", ) remote_file( name = "android-lifecycle-core.jar", - sha1 = "a2d487452376193fc8c103dd2b9bd5f2b1b44563", - url = "mvn:android.arch.core:common:jar:1.0.0", + sha1 = "8007981f7d7540d89cd18471b8e5dcd2b4f99167", + url = "mvn:android.arch.core:common:jar:1.1.0", +) + +remote_file( + name = "android-lifecycle-viewmodel-aar", + sha1 = "74ee369b874da61b5b81bebd7b8df0c2577309c8", + url = "mvn:android.arch.lifecycle:viewmodel:aar:1.1.0", ) remote_file( name = "lib-support-v4-support-compat-aar", - sha1 = "1e1c8ffc01d277d8f01dfd11d5d2ce3a2af4b98c", - url = "mvn:com.android.support:support-compat:aar:26.1.0", + sha1 = "a55ad550d0b84c7fec7ecca012690636062c0e64", + url = "mvn:com.android.support:support-compat:aar:27.1.1", ) remote_file( name = "lib-support-v4-support-core-utils-aar", - sha1 = "1bfaae21c4d5c5532c5e732071e9ce234cd58cff", - url = "mvn:com.android.support:support-core-utils:aar:26.1.0", + sha1 = "b3a7a4040fda0c5138dbc8c477103b6723b9dbe6", + url = "mvn:com.android.support:support-core-utils:aar:27.1.1", ) remote_file( name = "lib-support-v4-support-core-ui-aar", - sha1 = "e306308d54052a1ded7bf9c2f5c2fdf5152a1f22", - url = "mvn:com.android.support:support-core-ui:aar:26.1.0", + sha1 = "f9acdb8a4c3a9fe883fd7fa5efd3f0426bb9dcda", + url = "mvn:com.android.support:support-core-ui:aar:27.1.1", ) remote_file( name = "lib-support-v4-support-media-compat-aar", - sha1 = "09fb587f27cde19aa8f2e50c5c9ee645d9aec44d", - url = "mvn:com.android.support:support-media-compat:aar:26.1.0", + sha1 = "10e309e2cc22ff4cab30bd5f573e4bb30be707ad", + url = "mvn:com.android.support:support-media-compat:aar:27.1.1", ) remote_file( name = "lib-support-v4-support-fragment-aar", - sha1 = "ddacf369bb98dd6558606558de8ddcd53895cf91", - url = "mvn:com.android.support:support-fragment:aar:26.1.0", + sha1 = "eb8053ebf038b7561c29e5e8964664fac05f375e", + url = "mvn:com.android.support:support-fragment:aar:27.1.1", ) diff --git a/ReactAndroid/src/main/third-party/android/support/v7/appcompat-orig/BUCK b/ReactAndroid/src/main/third-party/android/support/v7/appcompat-orig/BUCK index 386e71b135fa90..2239c5692eaafd 100644 --- a/ReactAndroid/src/main/third-party/android/support/v7/appcompat-orig/BUCK +++ b/ReactAndroid/src/main/third-party/android/support/v7/appcompat-orig/BUCK @@ -57,6 +57,6 @@ python_binary( remote_file( name = "appcompat-binary-aar", - sha1 = "da5771a9ac6e8f3a461360eed3c6f921dc7580fd", - url = "mvn:com.android.support:appcompat-v7:aar:26.1.0", + sha1 = "22b1ef4ff9ef1a3513c18eb132d597eac6ef1a86", + url = "mvn:com.android.support:appcompat-v7:aar:27.1.1", ) diff --git a/local-cli/link/__fixtures__/android/build.gradle b/local-cli/link/__fixtures__/android/build.gradle index 9eb0a44ae5245f..70785a4faac7c8 100644 --- a/local-cli/link/__fixtures__/android/build.gradle +++ b/local-cli/link/__fixtures__/android/build.gradle @@ -1,5 +1,5 @@ dependencies { compile fileTree(dir: "libs", include: ["*.jar"]) - compile "com.android.support:appcompat-v7:26.1.0" + compile "com.android.support:appcompat-v7:27.1.1" compile "com.facebook.react:react-native:+" } diff --git a/local-cli/link/__fixtures__/android/patchedBuild.gradle b/local-cli/link/__fixtures__/android/patchedBuild.gradle index f6b9a22054cf0f..8cade796a256f3 100644 --- a/local-cli/link/__fixtures__/android/patchedBuild.gradle +++ b/local-cli/link/__fixtures__/android/patchedBuild.gradle @@ -4,6 +4,6 @@ dependencies { exclude(group: 'org.unwanted', module: 'test10') } compile fileTree(dir: "libs", include: ["*.jar"]) - compile "com.android.support:appcompat-v7:26.1.0" + compile "com.android.support:appcompat-v7:27.1.1" compile "com.facebook.react:react-native:+" } diff --git a/local-cli/templates/HelloWorld/android/build.gradle b/local-cli/templates/HelloWorld/android/build.gradle index 3ad24c19027c10..116463797c9bbe 100644 --- a/local-cli/templates/HelloWorld/android/build.gradle +++ b/local-cli/templates/HelloWorld/android/build.gradle @@ -36,7 +36,7 @@ ext { minSdkVersion = 16 compileSdkVersion = 26 targetSdkVersion = 26 - supportLibVersion = "26.1.0" + supportLibVersion = "27.1.1" } task wrapper(type: Wrapper) { From 02e7ce0219130b9fb04edb88cacf7d397d138005 Mon Sep 17 00:00:00 2001 From: Dulmandakh Date: Tue, 21 Aug 2018 17:12:50 -0700 Subject: [PATCH 088/273] use latest infer-annotations from maven (#20599) Summary: This PR removes infer-annotation from the repo and uses latest version of it from maven. Pull Request resolved: https://github.com/facebook/react-native/pull/20599 Differential Revision: D9437594 Pulled By: hramos fbshipit-source-id: 93c33041dd8a61b220c352fb187a23bb2dd1b4db --- ReactAndroid/build.gradle | 2 +- .../third-party/java/infer-annotations/BUCK | 8 +++++++- .../infer-annotations/infer-annotations-4.0.jar | Bin 14300 -> 0 bytes 3 files changed, 8 insertions(+), 2 deletions(-) delete mode 100644 ReactAndroid/src/main/third-party/java/infer-annotations/infer-annotations-4.0.jar diff --git a/ReactAndroid/build.gradle b/ReactAndroid/build.gradle index 81c74385caa2e0..7e92d969d36aaa 100644 --- a/ReactAndroid/build.gradle +++ b/ReactAndroid/build.gradle @@ -293,7 +293,7 @@ android { } dependencies { - compile fileTree(dir: 'src/main/third-party/java/infer-annotations/', include: ['*.jar']) + compile 'com.facebook.infer.annotation:infer-annotation:0.11.2' compile 'javax.inject:javax.inject:1' compile 'com.android.support:appcompat-v7:27.1.1' compile 'com.facebook.fbui.textlayoutbuilder:textlayoutbuilder:1.0.0' diff --git a/ReactAndroid/src/main/third-party/java/infer-annotations/BUCK b/ReactAndroid/src/main/third-party/java/infer-annotations/BUCK index 548d17fe77925a..1862f176ac2730 100644 --- a/ReactAndroid/src/main/third-party/java/infer-annotations/BUCK +++ b/ReactAndroid/src/main/third-party/java/infer-annotations/BUCK @@ -1,5 +1,11 @@ prebuilt_jar( name = "infer-annotations", - binary_jar = "infer-annotations-4.0.jar", + binary_jar = ":infer-annotations.jar", visibility = ["//ReactAndroid/..."], ) + +remote_file( + name = "infer-annotations.jar", + sha1 = "f514ff4ca022a579d9cf7524846988b646ae4491", + url = "mvn:com.facebook.infer.annotation:infer-annotation:jar:0.11.2", +) \ No newline at end of file diff --git a/ReactAndroid/src/main/third-party/java/infer-annotations/infer-annotations-4.0.jar b/ReactAndroid/src/main/third-party/java/infer-annotations/infer-annotations-4.0.jar deleted file mode 100644 index 418995d9a5df9fbed5c156542b18e3132d7a138e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14300 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 From 4b68b64e47f8fb18d6ea25c32af128bbd31af713 Mon Sep 17 00:00:00 2001 From: Dulmandakh Date: Wed, 22 Aug 2018 13:32:24 -0700 Subject: [PATCH 089/273] Remove TextLayoutBuilder from ReactAndroid dependency (#20600) Summary: This PR removes TextLayoutBuilder, which is not used anywhere. Pull Request resolved: https://github.com/facebook/react-native/pull/20600 Reviewed By: achen1 Differential Revision: D9367345 Pulled By: hramos fbshipit-source-id: 407a6a80f5c69650fcc7167b28214f7315beed2f --- ReactAndroid/build.gradle | 1 - ReactAndroid/proguard-rules.pro | 4 --- .../src/main/libraries/textlayoutbuilder/BUCK | 34 ------------------- 3 files changed, 39 deletions(-) delete mode 100644 ReactAndroid/src/main/libraries/textlayoutbuilder/BUCK diff --git a/ReactAndroid/build.gradle b/ReactAndroid/build.gradle index 7e92d969d36aaa..d14674d231e88b 100644 --- a/ReactAndroid/build.gradle +++ b/ReactAndroid/build.gradle @@ -296,7 +296,6 @@ dependencies { compile 'com.facebook.infer.annotation:infer-annotation:0.11.2' compile 'javax.inject:javax.inject:1' compile 'com.android.support:appcompat-v7:27.1.1' - compile 'com.facebook.fbui.textlayoutbuilder:textlayoutbuilder:1.0.0' compile "com.facebook.fresco:fresco:${FRESCO_VERSION}" compile "com.facebook.fresco:imagepipeline-okhttp3:${FRESCO_VERSION}" compile 'com.facebook.soloader:soloader:0.5.1' diff --git a/ReactAndroid/proguard-rules.pro b/ReactAndroid/proguard-rules.pro index 668d5bd472f8de..aa586132f2f853 100644 --- a/ReactAndroid/proguard-rules.pro +++ b/ReactAndroid/proguard-rules.pro @@ -51,10 +51,6 @@ -dontwarn com.facebook.react.** -keep,includedescriptorclasses class com.facebook.react.bridge.** { *; } -# TextLayoutBuilder uses a non-public Android constructor within StaticLayout. -# See libs/proxy/src/main/java/com/facebook/fbui/textlayoutbuilder/proxy for details. --dontwarn android.text.StaticLayout - # okhttp -keepattributes Signature diff --git a/ReactAndroid/src/main/libraries/textlayoutbuilder/BUCK b/ReactAndroid/src/main/libraries/textlayoutbuilder/BUCK deleted file mode 100644 index 60baf8edc408e8..00000000000000 --- a/ReactAndroid/src/main/libraries/textlayoutbuilder/BUCK +++ /dev/null @@ -1,34 +0,0 @@ -load("//ReactNative:DEFS.bzl", "rn_android_library", "rn_android_prebuilt_aar", "rn_prebuilt_jar") - -rn_android_library( - name = "textlayoutbuilder", - visibility = ["//ReactAndroid/..."], - exported_deps = [ - ":staticlayoutproxy", - ":textlayoutbuilder-base", - ], -) - -rn_android_prebuilt_aar( - name = "textlayoutbuilder-base", - aar = ":textlayoutbuilder-base-aar", - visibility = ["//ReactAndroid/..."], -) - -remote_file( - name = "textlayoutbuilder-base-aar", - sha1 = "29bc8e5a1e2b33944b88277652ee83092ae1dbc0", - url = "mvn:com.facebook.fbui.textlayoutbuilder:textlayoutbuilder:aar:1.0.0", -) - -rn_prebuilt_jar( - name = "staticlayoutproxy", - binary_jar = ":staticlayoutproxy.jar", - visibility = ["//ReactAndroid/..."], -) - -remote_file( - name = "staticlayoutproxy.jar", - sha1 = "f162442a19fff13995fbd51ba414d9ee05579080", - url = "mvn:com.facebook.fbui.textlayoutbuilder:staticlayout-proxy:jar:1.0", -) From 5992f8d5870963ce2c4f50035720753ecb0f7652 Mon Sep 17 00:00:00 2001 From: Dulmandakh Date: Wed, 22 Aug 2018 23:07:33 -0700 Subject: [PATCH 090/273] Bump compileSdkVersion to 27 and buildToolsVersion to 27.0.3 (#20777) Summary: I found that android support library 27.x (https://github.com/facebook/react-native/commit/874cca1ac258ec224bade999722d7a34c307def0) requires compileSdkVersion to be 27. Also found that many FB projects use SDK 27. Pull Request resolved: https://github.com/facebook/react-native/pull/20777 Differential Revision: D9478431 Pulled By: hramos fbshipit-source-id: ca100f6b5b39e7d112926124423f9510a0efc291 --- .buckconfig | 2 +- .circleci/config.yml | 6 +++--- ContainerShip/Dockerfile.android-base | 4 ++-- RNTester/android/app/build.gradle | 4 ++-- ReactAndroid/build.gradle | 4 ++-- appveyor.yml | 4 ++-- local-cli/templates/HelloWorld/android/build.gradle | 4 ++-- scripts/.tests.env | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.buckconfig b/.buckconfig index a4c6d696ba66b7..0d97d1b1f69fe8 100644 --- a/.buckconfig +++ b/.buckconfig @@ -1,6 +1,6 @@ [android] - target = android-26 + target = android-27 [download] max_number_of_retries = 3 diff --git a/.circleci/config.yml b/.circleci/config.yml index e7bfb892a6dd5e..ed652d791485f0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -28,11 +28,11 @@ aliases: - &restore-cache-android-packages keys: - - v1-android-sdkmanager-packages-api-26-alpha-{{ checksum "scripts/.tests.env" }} + - v1-android-sdkmanager-packages-api-27-alpha-{{ checksum "scripts/.tests.env" }} - &save-cache-android-packages paths: - /opt/android/sdk - key: v1-android-sdkmanager-packages-api-26-alpha-{{ checksum "scripts/.tests.env" }} + key: v1-android-sdkmanager-packages-api-27-alpha-{{ checksum "scripts/.tests.env" }} - &restore-cache-gradle keys: @@ -334,7 +334,7 @@ js_defaults: &js_defaults android_defaults: &android_defaults <<: *defaults docker: - - image: circleci/android:api-26-node8-alpha + - image: circleci/android:api-27-node8-alpha resource_class: "large" environment: - TERM: "dumb" diff --git a/ContainerShip/Dockerfile.android-base b/ContainerShip/Dockerfile.android-base index 5d19bc7f1e9457..6cbc6438c75bdf 100644 --- a/ContainerShip/Dockerfile.android-base +++ b/ContainerShip/Dockerfile.android-base @@ -18,8 +18,8 @@ LABEL maintainer="Héctor Ramos " # set default build arguments ARG SDK_VERSION=sdk-tools-linux-3859397.zip -ARG ANDROID_BUILD_VERSION=26 -ARG ANDROID_TOOLS_VERSION=26.0.3 +ARG ANDROID_BUILD_VERSION=27 +ARG ANDROID_TOOLS_VERSION=27.0.3 ARG BUCK_VERSION=v2018.07.23.01 ARG NDK_VERSION=17b ARG NODE_VERSION=8.10.0 diff --git a/RNTester/android/app/build.gradle b/RNTester/android/app/build.gradle index f69c094c17660a..3cacfe0409cb94 100644 --- a/RNTester/android/app/build.gradle +++ b/RNTester/android/app/build.gradle @@ -84,8 +84,8 @@ def enableSeparateBuildPerCPUArchitecture = false def enableProguardInReleaseBuilds = true android { - compileSdkVersion 26 - buildToolsVersion "26.0.3" + compileSdkVersion 27 + buildToolsVersion "27.0.3" defaultConfig { applicationId "com.facebook.react.uiapp" diff --git a/ReactAndroid/build.gradle b/ReactAndroid/build.gradle index d14674d231e88b..54a139e71fa6a4 100644 --- a/ReactAndroid/build.gradle +++ b/ReactAndroid/build.gradle @@ -245,8 +245,8 @@ task packageReactNdkLibsForBuck(dependsOn: packageReactNdkLibs, type: Copy) { } android { - compileSdkVersion 26 - buildToolsVersion "26.0.3" + compileSdkVersion 27 + buildToolsVersion "27.0.3" defaultConfig { minSdkVersion 16 diff --git a/appveyor.yml b/appveyor.yml index 3d5c4336a652cd..61fe51b3069ac6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,8 +1,8 @@ environment: ANDROID_HOME: "C:\\android-sdk-windows" ANDROID_NDK: "C:\\android-sdk-windows\\android-ndk-r17b" - ANDROID_BUILD_VERSION: 26 - ANDROID_TOOLS_VERSION: 26.0.3 + ANDROID_BUILD_VERSION: 27 + ANDROID_TOOLS_VERSION: 27.0.3 GRADLE_OPTS: -Dorg.gradle.daemon=false diff --git a/local-cli/templates/HelloWorld/android/build.gradle b/local-cli/templates/HelloWorld/android/build.gradle index 116463797c9bbe..8638267d1be79c 100644 --- a/local-cli/templates/HelloWorld/android/build.gradle +++ b/local-cli/templates/HelloWorld/android/build.gradle @@ -32,9 +32,9 @@ allprojects { } ext { - buildToolsVersion = "26.0.3" + buildToolsVersion = "27.0.3" minSdkVersion = 16 - compileSdkVersion = 26 + compileSdkVersion = 27 targetSdkVersion = 26 supportLibVersion = "27.1.1" } diff --git a/scripts/.tests.env b/scripts/.tests.env index e9d918ec476ec1..17a2ac9e13eaab 100644 --- a/scripts/.tests.env +++ b/scripts/.tests.env @@ -4,9 +4,9 @@ ## ANDROID ## # Android SDK Build Tools revision -export ANDROID_SDK_BUILD_TOOLS_REVISION=26.0.3 +export ANDROID_SDK_BUILD_TOOLS_REVISION=27.0.3 # Android API Level we build with -export ANDROID_SDK_BUILD_API_LEVEL="26" +export ANDROID_SDK_BUILD_API_LEVEL="27" # Google APIs for Android level export ANDROID_GOOGLE_API_LEVEL="23" # Minimum Android API Level we target From 6eac2d4e2f5f697043b495002872bfac3e8595cb Mon Sep 17 00:00:00 2001 From: gengjiawen Date: Wed, 22 Aug 2018 23:12:41 -0700 Subject: [PATCH 091/273] bump android gradle to 3.1.4 (#20767) Summary: Bump android gradle plugin to 3.1.4. We have been stay to 2.x too long. With 3.x we can have instant run and great performance and new features brought by google. Also thanks to CFKevinRef great pr to make this possible. pass all current ci. I have also tested RNTester release version works without crash. https://github.com/facebook/react-native/pull/17967. [GENERAL] [ANDROID] [FEATURE] - bump android gradle to 3.1.4 Pull Request resolved: https://github.com/facebook/react-native/pull/20767 Differential Revision: D9437576 Pulled By: hramos fbshipit-source-id: 6084056a1390582a75a879918f2538b0480f6299 --- RNTester/android/app/build.gradle | 6 +-- ReactAndroid/build.gradle | 42 +++++++++---------- build.gradle | 12 ++---- .../HelloWorld/android/app/build.gradle | 6 +-- .../templates/HelloWorld/android/build.gradle | 12 ++---- 5 files changed, 33 insertions(+), 45 deletions(-) diff --git a/RNTester/android/app/build.gradle b/RNTester/android/app/build.gradle index 3cacfe0409cb94..bc2423dd6fa257 100644 --- a/RNTester/android/app/build.gradle +++ b/RNTester/android/app/build.gradle @@ -140,9 +140,9 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:27.1.1' + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:appcompat-v7:27.1.1' // Build React Native from source - compile project(':ReactAndroid') + implementation project(':ReactAndroid') } diff --git a/ReactAndroid/build.gradle b/ReactAndroid/build.gradle index 54a139e71fa6a4..7c88ab3019456d 100644 --- a/ReactAndroid/build.gradle +++ b/ReactAndroid/build.gradle @@ -293,29 +293,29 @@ android { } dependencies { - compile 'com.facebook.infer.annotation:infer-annotation:0.11.2' - compile 'javax.inject:javax.inject:1' - compile 'com.android.support:appcompat-v7:27.1.1' - compile "com.facebook.fresco:fresco:${FRESCO_VERSION}" - compile "com.facebook.fresco:imagepipeline-okhttp3:${FRESCO_VERSION}" - compile 'com.facebook.soloader:soloader:0.5.1' - compile 'com.google.code.findbugs:jsr305:3.0.2' - compile "com.squareup.okhttp3:okhttp:${OKHTTP_VERSION}" - compile "com.squareup.okhttp3:okhttp-urlconnection:${OKHTTP_VERSION}" - compile 'com.squareup.okio:okio:1.14.0' + api 'com.facebook.infer.annotation:infer-annotation:0.11.2' + api 'javax.inject:javax.inject:1' + api 'com.android.support:appcompat-v7:27.1.1' + api "com.facebook.fresco:fresco:${FRESCO_VERSION}" + api "com.facebook.fresco:imagepipeline-okhttp3:${FRESCO_VERSION}" + api 'com.facebook.soloader:soloader:0.5.1' + api 'com.google.code.findbugs:jsr305:3.0.2' + api "com.squareup.okhttp3:okhttp:${OKHTTP_VERSION}" + api "com.squareup.okhttp3:okhttp-urlconnection:${OKHTTP_VERSION}" + api 'com.squareup.okio:okio:1.14.0' compile 'org.webkit:android-jsc:r174650' - testCompile "junit:junit:${JUNIT_VERSION}" - testCompile "org.powermock:powermock-api-mockito:${POWERMOCK_VERSION}" - testCompile "org.powermock:powermock-module-junit4-rule:${POWERMOCK_VERSION}" - testCompile "org.powermock:powermock-classloading-xstream:${POWERMOCK_VERSION}" - testCompile "org.mockito:mockito-core:${MOCKITO_CORE_VERSION}" - testCompile "org.easytesting:fest-assert-core:${FEST_ASSERT_CORE_VERSION}" - testCompile "org.robolectric:robolectric:${ROBOLECTRIC_VERSION}" - - androidTestCompile fileTree(dir: 'src/main/third-party/java/buck-android-support/', include: ['*.jar']) - androidTestCompile 'com.android.support.test:runner:0.3' - androidTestCompile "org.mockito:mockito-core:${MOCKITO_CORE_VERSION}" + testImplementation "junit:junit:${JUNIT_VERSION}" + testImplementation "org.powermock:powermock-api-mockito:${POWERMOCK_VERSION}" + testImplementation "org.powermock:powermock-module-junit4-rule:${POWERMOCK_VERSION}" + testImplementation "org.powermock:powermock-classloading-xstream:${POWERMOCK_VERSION}" + testImplementation "org.mockito:mockito-core:${MOCKITO_CORE_VERSION}" + testImplementation "org.easytesting:fest-assert-core:${FEST_ASSERT_CORE_VERSION}" + testImplementation "org.robolectric:robolectric:${ROBOLECTRIC_VERSION}" + + androidTestImplementation fileTree(dir: 'src/main/third-party/java/buck-android-support/', include: ['*.jar']) + androidTestImplementation 'com.android.support.test:runner:0.3' + androidTestImplementation "org.mockito:mockito-core:${MOCKITO_CORE_VERSION}" } apply from: 'release.gradle' diff --git a/build.gradle b/build.gradle index 6128d679600d28..582fa465717225 100644 --- a/build.gradle +++ b/build.gradle @@ -7,13 +7,10 @@ buildscript { repositories { jcenter() mavenLocal() - maven { - url 'https://maven.google.com/' - name 'Google' - } + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.1.4' classpath 'de.undercouch:gradle-download-task:3.4.3' // NOTE: Do not place your application dependencies here; they belong @@ -25,10 +22,7 @@ allprojects { repositories { jcenter() mavenLocal() - maven { - url 'https://maven.google.com/' - name 'Google' - } + google() def androidSdk = System.getenv("ANDROID_SDK") maven { diff --git a/local-cli/templates/HelloWorld/android/app/build.gradle b/local-cli/templates/HelloWorld/android/app/build.gradle index 31a0da9a576ea7..793eae821101a8 100644 --- a/local-cli/templates/HelloWorld/android/app/build.gradle +++ b/local-cli/templates/HelloWorld/android/app/build.gradle @@ -137,9 +137,9 @@ android { } dependencies { - compile fileTree(dir: "libs", include: ["*.jar"]) - compile "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}" - compile "com.facebook.react:react-native:+" // From node_modules + implementation fileTree(dir: "libs", include: ["*.jar"]) + implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}" + implementation "com.facebook.react:react-native:+" // From node_modules } // Run this once to be able to run the application with BUCK diff --git a/local-cli/templates/HelloWorld/android/build.gradle b/local-cli/templates/HelloWorld/android/build.gradle index 8638267d1be79c..0c58813ffc864e 100644 --- a/local-cli/templates/HelloWorld/android/build.gradle +++ b/local-cli/templates/HelloWorld/android/build.gradle @@ -3,13 +3,10 @@ buildscript { repositories { jcenter() - maven { - url 'https://maven.google.com/' - name 'Google' - } + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.1.4' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -24,10 +21,7 @@ allprojects { // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm url "$rootDir/../node_modules/react-native/android" } - maven { - url 'https://maven.google.com/' - name 'Google' - } + google() } } From a7d44dd350f3390feaea20782919bbee2008f0bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Wed, 22 Aug 2018 23:20:05 -0700 Subject: [PATCH 092/273] Use one time password when publishing to npm (#20701) Summary: This pull request addresses the failing publish-npm.js script from earlier this week. For background, last month we reset all npm access tokens for any package related to Facebook, and we now require all accounts with publish permissions to have two factor enabled. The publish-npm.js script relied on one such token that is configured in Circle CI as a envvar. The token has been updated in Circle CI, but we now need a way of passing the one time password to npm. With this PR, we can now grab the otp from Circle CI's envvars. Considering otps are ephemeral, this requires the NPM_CONFIG_OTP envvar to be set by someone with publishing permissions anytime a new release will be pushed to npm. The token is short lived, but it would still be good to clear the envvar after the package is published. Circle CI envvars are not passed on to PR/forked builds. This PR is effectively a breaking change for the release process, as the publish step will not succeed if the OTP is not valid. OTPs are short-lived, and the publish_npm_package job will definitely outlive the token. Unfortunately this will require some timing to get right, but the alternative is to ssh into the Circle CI machine and re-run the `npm publish --otp` command, which again would still require someone with publish access to provide the otp. Pull Request resolved: https://github.com/facebook/react-native/pull/20701 Differential Revision: D9478488 Pulled By: hramos fbshipit-source-id: 6af631a9cb425271b98c03d158aec390ebc95304 --- .circleci/config.yml | 22 +++++++++++++++------- scripts/publish-npm.js | 24 ++++++++++++++---------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ed652d791485f0..87bf7795436483 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -596,8 +596,10 @@ jobs: publish_npm_package: <<: *android_defaults steps: - - attach_workspace: - at: ~/react-native + - checkout + + - restore-cache: *restore-yarn-cache + - run: *yarn # Configure Android SDK and related dependencies - run: *configure-android-path @@ -624,13 +626,19 @@ jobs: - run: *yarn - run: - name: Publish React Native Package + name: Authenticate with npm + command: echo "//registry.npmjs.org/:_authToken=${CIRCLE_NPM_TOKEN}" > ~/.npmrc + + - run: + name: Authenticate git user command: | - echo "//registry.npmjs.org/:_authToken=${CIRCLE_NPM_TOKEN}" > ~/.npmrc - git config --global user.email "reactjs-bot@users.noreply.github.com" + git config --global user.email "react-native-bot@users.noreply.github.com" git config --global user.name "npm Deployment Script" - echo "machine github.com login reactjs-bot password $GITHUB_TOKEN" > ~/.netrc - node ./scripts/publish-npm.js + echo "machine github.com login react-native-bot password $GITHUB_TOKEN" > ~/.netrc + + - run: + name: Publish React Native Package + command: node ./scripts/publish-npm.js # Workflows enables us to run multiple jobs in parallel workflows: diff --git a/scripts/publish-npm.js b/scripts/publish-npm.js index f9492a93577646..5c1658112caf63 100644 --- a/scripts/publish-npm.js +++ b/scripts/publish-npm.js @@ -51,6 +51,7 @@ require('shelljs/global'); const buildBranch = process.env.CIRCLE_BRANCH; +const otp = process.env.NPM_CONFIG_OTP; let branchVersion; if (buildBranch.indexOf('-stable') !== -1) { @@ -79,7 +80,7 @@ const tagsWithVersion = exec(`git ls-remote origin | grep ${currentCommit}`, { if (tagsWithVersion.length === 0) { echo( - "Error: Can't find version tag in current commit. To deploy to NPM you must add tag v0.XY.Z[-rc] to your commit", + 'Error: Cannot find version tag in current commit. To deploy to NPM you must add tag v0.XY.Z[-rc] to your commit', ); exit(1); } @@ -96,7 +97,7 @@ if (tagsWithVersion[0].indexOf('-rc') === -1) { // -------- Generating Android Artifacts with JavaDoc if (exec('./gradlew :ReactAndroid:installArchives').code) { - echo("Couldn't generate artifacts"); + echo('Could not generate artifacts'); exit(1); } @@ -121,15 +122,18 @@ artifacts.forEach(name => { } }); -if (releaseVersion.indexOf('-rc') === -1) { - // release, package will be installed by default - exec('npm publish'); +// if version contains -rc, tag as prerelease +const tagFlag = releaseVersion.indexOf('-rc') === -1 ? '' : '--tag next'; + +// use otp from envvars if available +const otpFlag = otp ? `--otp ${otp}` : ''; + +if (exec(`npm publish ${tagFlag} ${otpFlag}`).code) { + echo('Failed to publish package to npm'); + exit(1); } else { - // RC release, package will be installed only if users specifically do it - exec('npm publish --tag next'); + echo(`Published to npm ${releaseVersion}`); + exit(0); } -echo(`Published to npm ${releaseVersion}`); - -exit(0); /*eslint-enable no-undef */ From be6076657283d900a7dbcf81cecaaeae6069c961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Thu, 23 Aug 2018 10:33:09 -0700 Subject: [PATCH 093/273] Bump iOS min in Readme (#20805) Summary: iOS 8 was dropped as of 0.56. Pull Request resolved: https://github.com/facebook/react-native/pull/20805 Differential Revision: D9481968 Pulled By: hramos fbshipit-source-id: 23e74ac3145ba92e2c119be365f2435e290c3f61 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7823b332a12a2d..037d159096b95f 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ The focus of React Native is on developer efficiency across all the platforms yo See the official [React Native website](https://facebook.github.io/react-native/) for an introduction to React Native. -Supported operating systems are >= Android 4.1 (API 16) and >= iOS 8.0. +Supported operating systems are >= Android 4.1 (API 16) and >= iOS 9.0. - [Getting Started](#getting-started) - [Documentation](#documentation) From 2f6e172fec328e1cd9fda2e5f6bd1c2559e9102b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Thu, 23 Aug 2018 15:02:56 -0700 Subject: [PATCH 094/273] Gate failing steps behind a username check (#20818) Summary: There are some steps known to be failing on master. This pollutes checks for unrelated PRs. This PR will make it so that PRs submitted by anyone other than myself will no-op on these steps. Future work: Have an array of whitelisted contributors, and make it much easier to turn individual tests on and off. Pull Request resolved: https://github.com/facebook/react-native/pull/20818 Differential Revision: D9484946 Pulled By: hramos fbshipit-source-id: d6c187b341f13552b33d0f1d569b65f6c66ae48f --- .circleci/config.yml | 66 ++++++++++++--------------- scripts/circleci/exec_author_check.sh | 10 ++++ 2 files changed, 38 insertions(+), 38 deletions(-) create mode 100755 scripts/circleci/exec_author_check.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index 87bf7795436483..67ebb9a4f3085d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -287,33 +287,32 @@ aliases: name: tvOS Test Suite command: ./scripts/objc-test-tvos.sh test - - &run-podspec-tests - name: Test CocoaPods (Ignoring failures) + - &display-broken-tests-warning + name: Running broken tests (Ignore any failures past this point) command: | - echo 'The following step is known to be failing in master, and any failures will be ignored.' - scripts/circleci/exec_swallow_error.sh ./scripts/process-podspecs.sh + echo 'The following steps are known to be failing on master.' + echo 'They will no-op for most users.' + echo 'PRs that bring these back to green are appreciated.' + + - &run-podspec-tests + name: Test CocoaPods (Disabled) + command: ./scripts/circleci/exec_author_check.sh ./scripts/process-podspecs.sh - &run-e2e-tests - name: End-to-End Test Suite - command: node ./scripts/run-ci-e2e-tests.js --android --ios --tvos --js --retries 3; + name: End-to-End Test Suite (Disabled) + command: ./scripts/circleci/exec_author_check.sh node ./scripts/run-ci-e2e-tests.js --android --ios --tvos --js --retries 3; - &run-objc-ios-e2e-tests - name: iOS End-to-End Test Suite (Ignoring failures) - command: | - echo 'The following step is known to be failing in master, and any failures will be ignored.' - scripts/circleci/exec_swallow_error.sh node ./scripts/run-ci-e2e-tests.js --ios --retries 3; + name: iOS End-to-End Test Suite (Disabled) + command: ./scripts/circleci/exec_author_check.sh node ./scripts/run-ci-e2e-tests.js --ios --retries 3; - &run-objc-tvos-e2e-tests - name: tvOS End-to-End Test Suite (Ignoring failures) - command: | - echo 'The following step is known to be failing in master, and any failures will be ignored.' - scripts/circleci/exec_swallow_error.sh node ./scripts/run-ci-e2e-tests.js --tvos --js --retries 3; + name: tvOS End-to-End Test Suite (Disabled) + command: ./scripts/circleci/exec_author_check.sh node ./scripts/run-ci-e2e-tests.js --tvos --js --retries 3; - &run-android-e2e-tests - name: Android End-to-End Test Suite (Ignoring failures) - command: | - echo 'The following step is known to be failing in master, and any failures will be ignored.' - scripts/circleci/exec_swallow_error.sh node ./scripts/run-ci-e2e-tests.js --android --retries 3; + name: Android End-to-End Test Suite (Disabled) + command: ./scripts/circleci/exec_author_check.sh node ./scripts/run-ci-e2e-tests.js --android --retries 3; - &run-js-e2e-tests name: JavaScript End-to-End Test Suite @@ -426,10 +425,8 @@ jobs: - run: *run-objc-ios-tests - run: *run-objc-tvos-tests - # The following are "disabled" - the steps will - # still run, but failures will be ignored. - # This is good for debugging flaky CI steps. - # TODO: Reenable as soon as they are in working order. + # TODO: Fix these failing tests. + - run: *display-broken-tests-warning - run: *run-podspec-tests - run: *run-objc-ios-e2e-tests - run: *run-objc-tvos-e2e-tests @@ -458,20 +455,15 @@ jobs: brew install applesimutils node -v - run: *yarn - # The following are "disabled" - the steps will - # still run, but failures will be ignored. - # This is good for debugging flaky CI steps. - # TODO: Reenable as soon as they are in working order. + - run: - name: Build iOS app for simulator (Ignoring failures) - command: | - echo 'The following step is known to be failing in master, and any failures will be ignored.' - scripts/circleci/exec_swallow_error.sh yarn run build-ios-e2e + name: Build iOS app for simulator + command: yarn run build-ios-e2e + # TODO: Fix these failing tests. + - run: *display-broken-tests-warning - run: - name: Run Detox Tests (Ignoring failures) - command: | - echo 'The following step is known to be failing in master, and any failures will be ignored.' - scripts/circleci/exec_swallow_error.sh yarn run test-ios-e2e + name: Run Detox Tests (Disabled) + command: ./scripts/circleci/exec_author_check.sh yarn run test-ios-e2e # Set up an Android environment for downstream jobs test_android: @@ -536,10 +528,8 @@ jobs: - run: *build-android-rntester-app # Run Android end-to-end tests - # The following are "disabled" - the steps will - # still run, but failures will be ignored. - # This is good for debugging flaky CI steps. - # TODO: Reenable as soon as they are in working order. + # TODO: Fix these failing tests. + - run: *display-broken-tests-warning - run: *run-android-e2e-tests # Collect Results diff --git a/scripts/circleci/exec_author_check.sh b/scripts/circleci/exec_author_check.sh new file mode 100755 index 00000000000000..b1fa20cad0eda1 --- /dev/null +++ b/scripts/circleci/exec_author_check.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# This is meant to be used to keep failing tests from +# running for regular contributors, while still letting +# them run on PRs submitted by core contributors. +# Useful when working to bring a failing step back to green. + +# Add yourself here if you'd like to pass the whitelist. +# Once N > 1 we should change this into an array check. +echo "Skipping" "$@" ", branch is stable" From 60b11b05a3caf3f8bd8e47f59bac8022f3aced5e Mon Sep 17 00:00:00 2001 From: gengjiawen Date: Thu, 23 Aug 2018 12:05:54 -0700 Subject: [PATCH 095/273] refine android config (#20731) Summary: By this change we can unify version early, like we can make kotlin version share in buildscript and app dependency the same time ([butterknife](https://github.com/JakeWharton/butterknife/blob/master/build.gradle) use the same). pass all current ci and one of my project https://github.com/gengjiawen/ReactNative64bitDemo. none [GENERAL] [ANDROID] [TEMPLATE] - refine android config Pull Request resolved: https://github.com/facebook/react-native/pull/20731 Differential Revision: D9482954 Pulled By: hramos fbshipit-source-id: d864adbdbc624bc311ccc5f44a15d0334d2d8a59 --- .../templates/HelloWorld/android/build.gradle | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/local-cli/templates/HelloWorld/android/build.gradle b/local-cli/templates/HelloWorld/android/build.gradle index 0c58813ffc864e..85d8f2f81e2bd3 100644 --- a/local-cli/templates/HelloWorld/android/build.gradle +++ b/local-cli/templates/HelloWorld/android/build.gradle @@ -1,6 +1,13 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { + ext { + buildToolsVersion = "27.0.3" + minSdkVersion = 16 + compileSdkVersion = 27 + targetSdkVersion = 26 + supportLibVersion = "27.1.1" + } repositories { jcenter() google() @@ -25,13 +32,6 @@ allprojects { } } -ext { - buildToolsVersion = "27.0.3" - minSdkVersion = 16 - compileSdkVersion = 27 - targetSdkVersion = 26 - supportLibVersion = "27.1.1" -} task wrapper(type: Wrapper) { gradleVersion = '4.4' From 7ae186cd853770dcfc3a7d623bd9331040d9a25e Mon Sep 17 00:00:00 2001 From: Vladimir Zdravkovic Date: Thu, 23 Aug 2018 14:09:19 -0700 Subject: [PATCH 096/273] Updated the glog library version from 0.3.4 to 0.3.5 (#20811) Summary: While the original reason for this change was because of an issue #20780, with further investigation I concluded that the issue is till present for this combo of versions: glog - 0.3.5 google-cast-sdk - 4.3.1 Downgrading google-cast-sdk to 4.3.0 fixed the build issue. Release Notes: -------------- Updated glog version from 0.3.4 to 0.3.5 for iOS [IOS] [ENHANCEMENT] [GLOG] Pull Request resolved: https://github.com/facebook/react-native/pull/20811 Differential Revision: D9485221 Pulled By: hramos fbshipit-source-id: 65caf0839588384a5229a6165506dc6ef62e5fc5 --- RNTester/Podfile.lock | 10 +- .../contents.xcworkspacedata | 10 ++ React/React.xcodeproj/project.pbxproj | 111 +++++++++--------- React/third-party.xcconfig | 2 +- scripts/ios-install-third-party.sh | 4 +- third-party-podspecs/DoubleConversion.podspec | 2 +- third-party-podspecs/glog.podspec | 2 +- 7 files changed, 73 insertions(+), 68 deletions(-) create mode 100644 RNTester/RNTesterPods.xcworkspace/contents.xcworkspacedata diff --git a/RNTester/Podfile.lock b/RNTester/Podfile.lock index e4ba550e92c676..06b931a60134f3 100644 --- a/RNTester/Podfile.lock +++ b/RNTester/Podfile.lock @@ -1,11 +1,11 @@ PODS: - boost-for-react-native (1.63.0) - - DoubleConversion (1.1.5) + - DoubleConversion (1.1.6) - Folly (2016.10.31.00): - boost-for-react-native - DoubleConversion - glog - - glog (0.3.4) + - glog (0.3.5) - React/ART (1000.0.0): - React/Core - React/Core (1000.0.0): @@ -101,12 +101,12 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c - DoubleConversion: a9706f16e388b53ff12cca34473428ee29746a26 + DoubleConversion: bb338842f62ab1d708ceb63ec3d999f0f3d98ecd Folly: c89ac2d5c6ab169cd7397ef27485c44f35f742c7 - glog: 3931855c9cc99c3fab1355fc162fe369162d8183 + glog: e8acf0ebbf99759d3ff18c86c292a5898282dcde React: 1fe0eb13d90b625d94c3b117c274dcfd2e760e11 yoga: b1ce48b6cf950b98deae82838f5173ea7cf89e85 PODFILE CHECKSUM: 7af77fbc34af9646e8c6389e7e2c0b4663bb16d9 -COCOAPODS: 1.5.2 +COCOAPODS: 1.5.3 diff --git a/RNTester/RNTesterPods.xcworkspace/contents.xcworkspacedata b/RNTester/RNTesterPods.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000000000..96d9c7f00fbc33 --- /dev/null +++ b/RNTester/RNTesterPods.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/React/React.xcodeproj/project.pbxproj b/React/React.xcodeproj/project.pbxproj index 1f8c1e4b1ebea6..aacbe191afebb0 100644 --- a/React/React.xcodeproj/project.pbxproj +++ b/React/React.xcodeproj/project.pbxproj @@ -1920,58 +1920,58 @@ 137327E61AA5CF210034F82E /* RCTTabBarManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTabBarManager.m; sourceTree = ""; }; 1384E2061E806D4E00545659 /* RCTNativeModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTNativeModule.h; sourceTree = ""; }; 1384E2071E806D4E00545659 /* RCTNativeModule.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTNativeModule.mm; sourceTree = ""; }; - 139D7E391E25C5A300323FB7 /* bignum-dtoa.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "bignum-dtoa.cc"; path = "double-conversion-1.1.5/src/bignum-dtoa.cc"; sourceTree = ""; }; - 139D7E3A1E25C5A300323FB7 /* bignum-dtoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "bignum-dtoa.h"; path = "double-conversion-1.1.5/src/bignum-dtoa.h"; sourceTree = ""; }; - 139D7E3B1E25C5A300323FB7 /* bignum.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bignum.cc; path = "double-conversion-1.1.5/src/bignum.cc"; sourceTree = ""; }; - 139D7E3C1E25C5A300323FB7 /* bignum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bignum.h; path = "double-conversion-1.1.5/src/bignum.h"; sourceTree = ""; }; - 139D7E3D1E25C5A300323FB7 /* cached-powers.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "cached-powers.cc"; path = "double-conversion-1.1.5/src/cached-powers.cc"; sourceTree = ""; }; - 139D7E3E1E25C5A300323FB7 /* cached-powers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "cached-powers.h"; path = "double-conversion-1.1.5/src/cached-powers.h"; sourceTree = ""; }; - 139D7E3F1E25C5A300323FB7 /* diy-fp.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "diy-fp.cc"; path = "double-conversion-1.1.5/src/diy-fp.cc"; sourceTree = ""; }; - 139D7E401E25C5A300323FB7 /* diy-fp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "diy-fp.h"; path = "double-conversion-1.1.5/src/diy-fp.h"; sourceTree = ""; }; - 139D7E411E25C5A300323FB7 /* double-conversion.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "double-conversion.cc"; path = "double-conversion-1.1.5/src/double-conversion.cc"; sourceTree = ""; }; - 139D7E421E25C5A300323FB7 /* double-conversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "double-conversion.h"; path = "double-conversion-1.1.5/src/double-conversion.h"; sourceTree = ""; }; - 139D7E431E25C5A300323FB7 /* fast-dtoa.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "fast-dtoa.cc"; path = "double-conversion-1.1.5/src/fast-dtoa.cc"; sourceTree = ""; }; - 139D7E441E25C5A300323FB7 /* fast-dtoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "fast-dtoa.h"; path = "double-conversion-1.1.5/src/fast-dtoa.h"; sourceTree = ""; }; - 139D7E451E25C5A300323FB7 /* fixed-dtoa.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "fixed-dtoa.cc"; path = "double-conversion-1.1.5/src/fixed-dtoa.cc"; sourceTree = ""; }; - 139D7E461E25C5A300323FB7 /* fixed-dtoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "fixed-dtoa.h"; path = "double-conversion-1.1.5/src/fixed-dtoa.h"; sourceTree = ""; }; - 139D7E471E25C5A300323FB7 /* ieee.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ieee.h; path = "double-conversion-1.1.5/src/ieee.h"; sourceTree = ""; }; - 139D7E481E25C5A300323FB7 /* strtod.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = strtod.cc; path = "double-conversion-1.1.5/src/strtod.cc"; sourceTree = ""; }; - 139D7E491E25C5A300323FB7 /* strtod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = strtod.h; path = "double-conversion-1.1.5/src/strtod.h"; sourceTree = ""; }; - 139D7E4A1E25C5A300323FB7 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utils.h; path = "double-conversion-1.1.5/src/utils.h"; sourceTree = ""; }; + 139D7E391E25C5A300323FB7 /* bignum-dtoa.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "bignum-dtoa.cc"; path = "src/bignum-dtoa.cc"; sourceTree = ""; }; + 139D7E3A1E25C5A300323FB7 /* bignum-dtoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "bignum-dtoa.h"; path = "src/bignum-dtoa.h"; sourceTree = ""; }; + 139D7E3B1E25C5A300323FB7 /* bignum.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bignum.cc; path = src/bignum.cc; sourceTree = ""; }; + 139D7E3C1E25C5A300323FB7 /* bignum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bignum.h; path = src/bignum.h; sourceTree = ""; }; + 139D7E3D1E25C5A300323FB7 /* cached-powers.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "cached-powers.cc"; path = "src/cached-powers.cc"; sourceTree = ""; }; + 139D7E3E1E25C5A300323FB7 /* cached-powers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "cached-powers.h"; path = "src/cached-powers.h"; sourceTree = ""; }; + 139D7E3F1E25C5A300323FB7 /* diy-fp.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "diy-fp.cc"; path = "src/diy-fp.cc"; sourceTree = ""; }; + 139D7E401E25C5A300323FB7 /* diy-fp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "diy-fp.h"; path = "src/diy-fp.h"; sourceTree = ""; }; + 139D7E411E25C5A300323FB7 /* double-conversion.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "double-conversion.cc"; path = "src/double-conversion.cc"; sourceTree = ""; }; + 139D7E421E25C5A300323FB7 /* double-conversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "double-conversion.h"; path = "src/double-conversion.h"; sourceTree = ""; }; + 139D7E431E25C5A300323FB7 /* fast-dtoa.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "fast-dtoa.cc"; path = "src/fast-dtoa.cc"; sourceTree = ""; }; + 139D7E441E25C5A300323FB7 /* fast-dtoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "fast-dtoa.h"; path = "src/fast-dtoa.h"; sourceTree = ""; }; + 139D7E451E25C5A300323FB7 /* fixed-dtoa.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "fixed-dtoa.cc"; path = "src/fixed-dtoa.cc"; sourceTree = ""; }; + 139D7E461E25C5A300323FB7 /* fixed-dtoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "fixed-dtoa.h"; path = "src/fixed-dtoa.h"; sourceTree = ""; }; + 139D7E471E25C5A300323FB7 /* ieee.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ieee.h; path = src/ieee.h; sourceTree = ""; }; + 139D7E481E25C5A300323FB7 /* strtod.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = strtod.cc; path = src/strtod.cc; sourceTree = ""; }; + 139D7E491E25C5A300323FB7 /* strtod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = strtod.h; path = src/strtod.h; sourceTree = ""; }; + 139D7E4A1E25C5A300323FB7 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utils.h; path = src/utils.h; sourceTree = ""; }; 139D7E881E25C6D100323FB7 /* libdouble-conversion.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libdouble-conversion.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 139D7ECE1E25DB7D00323FB7 /* libthird-party.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libthird-party.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 139D7ED81E25DBDC00323FB7 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = config.h; path = "glog-0.3.4/src/config.h"; sourceTree = ""; }; - 139D7ED91E25DBDC00323FB7 /* demangle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = demangle.h; path = "glog-0.3.4/src/demangle.h"; sourceTree = ""; }; - 139D7EDA1E25DBDC00323FB7 /* logging.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = logging.cc; path = "glog-0.3.4/src/logging.cc"; sourceTree = ""; }; - 139D7EDB1E25DBDC00323FB7 /* raw_logging.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = raw_logging.cc; path = "glog-0.3.4/src/raw_logging.cc"; sourceTree = ""; }; - 139D7EDC1E25DBDC00323FB7 /* signalhandler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = signalhandler.cc; path = "glog-0.3.4/src/signalhandler.cc"; sourceTree = ""; }; - 139D7EDD1E25DBDC00323FB7 /* stacktrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stacktrace.h; path = "glog-0.3.4/src/stacktrace.h"; sourceTree = ""; }; - 139D7EDE1E25DBDC00323FB7 /* symbolize.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = symbolize.cc; path = "glog-0.3.4/src/symbolize.cc"; sourceTree = ""; }; - 139D7EDF1E25DBDC00323FB7 /* symbolize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = symbolize.h; path = "glog-0.3.4/src/symbolize.h"; sourceTree = ""; }; - 139D7EE01E25DBDC00323FB7 /* utilities.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utilities.cc; path = "glog-0.3.4/src/utilities.cc"; sourceTree = ""; }; - 139D7EE11E25DBDC00323FB7 /* utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utilities.h; path = "glog-0.3.4/src/utilities.h"; sourceTree = ""; }; - 139D7EE21E25DBDC00323FB7 /* vlog_is_on.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = vlog_is_on.cc; path = "glog-0.3.4/src/vlog_is_on.cc"; sourceTree = ""; }; - 139D7F081E25DE3700323FB7 /* demangle.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = demangle.cc; path = "glog-0.3.4/src/demangle.cc"; sourceTree = ""; }; + 139D7ED81E25DBDC00323FB7 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = config.h; path = "../third-party/glog-0.3.5/src/config.h"; sourceTree = ""; }; + 139D7ED91E25DBDC00323FB7 /* demangle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = demangle.h; path = "../third-party/glog-0.3.5/src/demangle.h"; sourceTree = ""; }; + 139D7EDA1E25DBDC00323FB7 /* logging.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = logging.cc; path = "../third-party/glog-0.3.5/src/logging.cc"; sourceTree = ""; }; + 139D7EDB1E25DBDC00323FB7 /* raw_logging.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = raw_logging.cc; path = "../third-party/glog-0.3.5/src/raw_logging.cc"; sourceTree = ""; }; + 139D7EDC1E25DBDC00323FB7 /* signalhandler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = signalhandler.cc; path = "../third-party/glog-0.3.5/src/signalhandler.cc"; sourceTree = ""; }; + 139D7EDD1E25DBDC00323FB7 /* stacktrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stacktrace.h; path = "../third-party/glog-0.3.5/src/stacktrace.h"; sourceTree = ""; }; + 139D7EDE1E25DBDC00323FB7 /* symbolize.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = symbolize.cc; path = "../third-party/glog-0.3.5/src/symbolize.cc"; sourceTree = ""; }; + 139D7EDF1E25DBDC00323FB7 /* symbolize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = symbolize.h; path = "../third-party/glog-0.3.5/src/symbolize.h"; sourceTree = ""; }; + 139D7EE01E25DBDC00323FB7 /* utilities.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utilities.cc; path = "../third-party/glog-0.3.5/src/utilities.cc"; sourceTree = ""; }; + 139D7EE11E25DBDC00323FB7 /* utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utilities.h; path = "../third-party/glog-0.3.5/src/utilities.h"; sourceTree = ""; }; + 139D7EE21E25DBDC00323FB7 /* vlog_is_on.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = vlog_is_on.cc; path = "../third-party/glog-0.3.5/src/vlog_is_on.cc"; sourceTree = ""; }; + 139D7F081E25DE3700323FB7 /* demangle.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = demangle.cc; path = "../third-party/glog-0.3.5/src/demangle.cc"; sourceTree = ""; }; 139D7F111E25DEC900323FB7 /* log_severity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = log_severity.h; sourceTree = ""; }; 139D7F121E25DEC900323FB7 /* logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = logging.h; sourceTree = ""; }; 139D7F141E25DEC900323FB7 /* raw_logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = raw_logging.h; sourceTree = ""; }; 139D7F161E25DEC900323FB7 /* stl_logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stl_logging.h; sourceTree = ""; }; 139D7F181E25DEC900323FB7 /* vlog_is_on.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vlog_is_on.h; sourceTree = ""; }; - 139D849C1E273B5600323FB7 /* AtomicIntrusiveLinkedList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AtomicIntrusiveLinkedList.h; path = "folly-2016.10.31.00/folly/AtomicIntrusiveLinkedList.h"; sourceTree = ""; }; - 139D849D1E273B5600323FB7 /* Bits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Bits.cpp; path = "folly-2016.10.31.00/folly/Bits.cpp"; sourceTree = ""; }; - 139D849E1E273B5600323FB7 /* Bits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Bits.h; path = "folly-2016.10.31.00/folly/Bits.h"; sourceTree = ""; }; - 139D849F1E273B5600323FB7 /* Conv.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Conv.cpp; path = "folly-2016.10.31.00/folly/Conv.cpp"; sourceTree = ""; }; - 139D84A01E273B5600323FB7 /* Conv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Conv.h; path = "folly-2016.10.31.00/folly/Conv.h"; sourceTree = ""; }; - 139D84A11E273B5600323FB7 /* dynamic-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "dynamic-inl.h"; path = "folly-2016.10.31.00/folly/dynamic-inl.h"; sourceTree = ""; }; - 139D84A21E273B5600323FB7 /* dynamic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dynamic.cpp; path = "folly-2016.10.31.00/folly/dynamic.cpp"; sourceTree = ""; }; - 139D84A31E273B5600323FB7 /* dynamic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dynamic.h; path = "folly-2016.10.31.00/folly/dynamic.h"; sourceTree = ""; }; - 139D84A41E273B5600323FB7 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Exception.h; path = "folly-2016.10.31.00/folly/Exception.h"; sourceTree = ""; }; - 139D84A71E273B5600323FB7 /* json.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = json.cpp; path = "folly-2016.10.31.00/folly/json.cpp"; sourceTree = ""; }; - 139D84A81E273B5600323FB7 /* json.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = json.h; path = "folly-2016.10.31.00/folly/json.h"; sourceTree = ""; }; - 139D84A91E273B5600323FB7 /* Memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Memory.h; path = "folly-2016.10.31.00/folly/Memory.h"; sourceTree = ""; }; - 139D84AA1E273B5600323FB7 /* MoveWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MoveWrapper.h; path = "folly-2016.10.31.00/folly/MoveWrapper.h"; sourceTree = ""; }; - 139D84AB1E273B5600323FB7 /* Optional.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Optional.h; path = "folly-2016.10.31.00/folly/Optional.h"; sourceTree = ""; }; - 139D84AC1E273B5600323FB7 /* ScopeGuard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScopeGuard.h; path = "folly-2016.10.31.00/folly/ScopeGuard.h"; sourceTree = ""; }; + 139D849C1E273B5600323FB7 /* AtomicIntrusiveLinkedList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AtomicIntrusiveLinkedList.h; path = "folly/AtomicIntrusiveLinkedList.h"; sourceTree = ""; }; + 139D849D1E273B5600323FB7 /* Bits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Bits.cpp; path = "folly/Bits.cpp"; sourceTree = ""; }; + 139D849E1E273B5600323FB7 /* Bits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Bits.h; path = "folly/Bits.h"; sourceTree = ""; }; + 139D849F1E273B5600323FB7 /* Conv.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Conv.cpp; path = "folly/Conv.cpp"; sourceTree = ""; }; + 139D84A01E273B5600323FB7 /* Conv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Conv.h; path = "folly/Conv.h"; sourceTree = ""; }; + 139D84A11E273B5600323FB7 /* dynamic-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "dynamic-inl.h"; path = "folly/dynamic-inl.h"; sourceTree = ""; }; + 139D84A21E273B5600323FB7 /* dynamic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dynamic.cpp; path = "folly/dynamic.cpp"; sourceTree = ""; }; + 139D84A31E273B5600323FB7 /* dynamic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dynamic.h; path = "folly/dynamic.h"; sourceTree = ""; }; + 139D84A41E273B5600323FB7 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Exception.h; path = "folly/Exception.h"; sourceTree = ""; }; + 139D84A71E273B5600323FB7 /* json.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = json.cpp; path = "folly/json.cpp"; sourceTree = ""; }; + 139D84A81E273B5600323FB7 /* json.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = json.h; path = "folly/json.h"; sourceTree = ""; }; + 139D84A91E273B5600323FB7 /* Memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Memory.h; path = "folly/Memory.h"; sourceTree = ""; }; + 139D84AA1E273B5600323FB7 /* MoveWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MoveWrapper.h; path = "folly/MoveWrapper.h"; sourceTree = ""; }; + 139D84AB1E273B5600323FB7 /* Optional.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Optional.h; path = "folly/Optional.h"; sourceTree = ""; }; + 139D84AC1E273B5600323FB7 /* ScopeGuard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScopeGuard.h; path = "folly/ScopeGuard.h"; sourceTree = ""; }; 13A0C2851B74F71200B29F6F /* RCTDevLoadingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = RCTDevLoadingView.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 13A0C2861B74F71200B29F6F /* RCTDevLoadingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTDevLoadingView.m; sourceTree = ""; }; 13A0C2871B74F71200B29F6F /* RCTDevMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = RCTDevMenu.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; @@ -2037,11 +2037,11 @@ 13E067541A70F44B002CDEE1 /* UIView+React.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+React.m"; sourceTree = ""; }; 13F17A831B8493E5007D4C75 /* RCTRedBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRedBox.h; sourceTree = ""; }; 13F17A841B8493E5007D4C75 /* RCTRedBox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRedBox.m; sourceTree = ""; }; - 13F887521E2971C500C3C7A1 /* Demangle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Demangle.cpp; path = "folly-2016.10.31.00/folly/Demangle.cpp"; sourceTree = ""; }; - 13F887531E2971C500C3C7A1 /* StringBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringBase.cpp; path = "folly-2016.10.31.00/folly/StringBase.cpp"; sourceTree = ""; }; - 13F887541E2971C500C3C7A1 /* Unicode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Unicode.cpp; path = "folly-2016.10.31.00/folly/Unicode.cpp"; sourceTree = ""; }; - 13F8879C1E29740700C3C7A1 /* BitsFunctexcept.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BitsFunctexcept.cpp; path = "folly-2016.10.31.00/folly/portability/BitsFunctexcept.cpp"; sourceTree = ""; }; - 13F887A01E2977D800C3C7A1 /* MallocImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MallocImpl.cpp; path = "folly-2016.10.31.00/folly/detail/MallocImpl.cpp"; sourceTree = ""; }; + 13F887521E2971C500C3C7A1 /* Demangle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Demangle.cpp; path = "folly/Demangle.cpp"; sourceTree = ""; }; + 13F887531E2971C500C3C7A1 /* StringBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringBase.cpp; path = "folly/StringBase.cpp"; sourceTree = ""; }; + 13F887541E2971C500C3C7A1 /* Unicode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Unicode.cpp; path = "folly/Unicode.cpp"; sourceTree = ""; }; + 13F8879C1E29740700C3C7A1 /* BitsFunctexcept.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BitsFunctexcept.cpp; path = "folly/portability/BitsFunctexcept.cpp"; sourceTree = ""; }; + 13F887A01E2977D800C3C7A1 /* MallocImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MallocImpl.cpp; path = "folly/detail/MallocImpl.cpp"; sourceTree = ""; }; 14200DA81AC179B3008EE6BA /* RCTJavaScriptLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTJavaScriptLoader.h; sourceTree = ""; }; 142014171B32094000CC17BA /* RCTPerformanceLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPerformanceLogger.m; sourceTree = ""; }; 142014181B32094000CC17BA /* RCTPerformanceLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPerformanceLogger.h; sourceTree = ""; }; @@ -2453,6 +2453,7 @@ 139D7E4A1E25C5A300323FB7 /* utils.h */, ); name = "double-conversion"; + path = "../third-party/double-conversion-1.1.6"; sourceTree = ""; }; 139D7ED71E25DB9200323FB7 /* glog */ = { @@ -2485,7 +2486,7 @@ 139D7F181E25DEC900323FB7 /* vlog_is_on.h */, ); name = glog; - path = "glog-0.3.4/src/glog"; + path = "../third-party/glog-0.3.5/src/glog"; sourceTree = ""; }; 139D849B1E2739EC00323FB7 /* folly */ = { @@ -2513,6 +2514,7 @@ 139D84AC1E273B5600323FB7 /* ScopeGuard.h */, ); name = folly; + path = "../third-party/folly-2016.10.31.00"; sourceTree = ""; }; 13B07FE01A69315300A75B9A /* Modules */ = { @@ -2810,7 +2812,6 @@ 139D7E381E25C55B00323FB7 /* double-conversion */, ); name = ThirdParty; - path = "../third-party"; sourceTree = ""; }; 53D123821FBF1D49001B8A10 /* Frameworks */ = { @@ -3995,12 +3996,6 @@ CreatedOnToolsVersion = 8.0; ProvisioningStyle = Automatic; }; - 3D383D211EBD27B6005632C8 = { - DevelopmentTeam = V9WTTPBFK9; - }; - 3D383D3D1EBD27B9005632C8 = { - DevelopmentTeam = V9WTTPBFK9; - }; 83CBBA2D1A601D0E00E9B192 = { CreatedOnToolsVersion = 6.1.1; }; diff --git a/React/third-party.xcconfig b/React/third-party.xcconfig index 24bf1727b3848c..1976b396c78388 100644 --- a/React/third-party.xcconfig +++ b/React/third-party.xcconfig @@ -6,5 +6,5 @@ // Copyright © 2017 Facebook. All rights reserved. // -HEADER_SEARCH_PATHS = $(SRCROOT)/../third-party/boost_1_63_0 $(SRCROOT)/../third-party/folly-2016.10.31.00 $(SRCROOT)/../third-party/glog-0.3.4/src +HEADER_SEARCH_PATHS = $(SRCROOT)/../third-party/boost_1_63_0 $(SRCROOT)/../third-party/folly-2016.10.31.00 $(SRCROOT)/../third-party/glog-0.3.5/src OTHER_CFLAGS = -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 diff --git a/scripts/ios-install-third-party.sh b/scripts/ios-install-third-party.sh index f10b23b32a6f28..c53292659fc9e6 100755 --- a/scripts/ios-install-third-party.sh +++ b/scripts/ios-install-third-party.sh @@ -61,7 +61,7 @@ mkdir -p third-party SCRIPTDIR=$(dirname "$0") -fetch_and_unpack glog-0.3.4.tar.gz https://github.com/google/glog/archive/v0.3.4.tar.gz 69f91cd5a1de35ead0bc4103ea87294b0206a456 "\"$SCRIPTDIR/ios-configure-glog.sh\"" -fetch_and_unpack double-conversion-1.1.5.tar.gz https://github.com/google/double-conversion/archive/v1.1.5.tar.gz 96a8aba1b4ce7d4a7a3c123be26c379c2fed1def +fetch_and_unpack glog-0.3.5.tar.gz https://github.com/google/glog/archive/v0.3.5.tar.gz 61067502c5f9769d111ea1ee3f74e6ddf0a5f9cc "\"$SCRIPTDIR/ios-configure-glog.sh\"" +fetch_and_unpack double-conversion-1.1.6.tar.gz https://github.com/google/double-conversion/archive/v1.1.6.tar.gz 1c7d88afde3aaeb97bb652776c627b49e132e8e0 fetch_and_unpack boost_1_63_0.tar.gz https://github.com/react-native-community/boost-for-react-native/releases/download/v1.63.0-0/boost_1_63_0.tar.gz c3f57e1d22a995e608983effbb752b54b6eab741 fetch_and_unpack folly-2016.10.31.00.tar.gz https://github.com/facebook/folly/archive/v2016.10.31.00.tar.gz fb8cdf8962d8c9d0c20a150b6ec3b75d1fa50696 diff --git a/third-party-podspecs/DoubleConversion.podspec b/third-party-podspecs/DoubleConversion.podspec index 42965eee743cf7..2ea6c84a4b02b6 100644 --- a/third-party-podspecs/DoubleConversion.podspec +++ b/third-party-podspecs/DoubleConversion.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'DoubleConversion' - spec.version = '1.1.5' + spec.version = '1.1.6' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/google/double-conversion' spec.summary = 'Efficient binary-decimal and decimal-binary conversion routines for IEEE doubles' diff --git a/third-party-podspecs/glog.podspec b/third-party-podspecs/glog.podspec index 03f106b4c64548..bc4bb1e182cf20 100644 --- a/third-party-podspecs/glog.podspec +++ b/third-party-podspecs/glog.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'glog' - spec.version = '0.3.4' + spec.version = '0.3.5' spec.license = { :type => 'Google', :file => 'COPYING' } spec.homepage = 'https://github.com/google/glog' spec.summary = 'Google logging module' From e38b92865050314fb77ef5f4f79cdea3e0bbbf11 Mon Sep 17 00:00:00 2001 From: Rafael Oleza Date: Thu, 23 Aug 2018 15:44:38 -0700 Subject: [PATCH 097/273] Standarize options passed to the transformer Summary: This is the first step to make transformers fully customizable (and not be tied to JS, or RN). In order to do that, I'm changing the signature of the transformers, which currently is: ``` function transformCode( filename: string, localPath: LocalPath, transformerPath: string, options: WorkerOptions, assetExts: $ReadOnlyArray, assetRegistryPath: string, minifierPath: string, asyncRequireModulePath: string, dynamicDepsInPackages: DynamicRequiresBehavior, ) ``` to be: ``` async function transformCode( filename: string, localPath: LocalPath, options: WorkerOptions, ) ``` (so basically, all the RN-custom properties are moved to `WorkerOptions`, which in the future will be a generic to allow anybody pass any random option to their transformers). In order to make all this work, I've had to get rid of the logic that calculates the base cache key hash based on a subset of worker options (the ones that Metro knows that are not going to change between runs). This could potentially cause a perf regression (since we're now making the hash calculation a bit more costly), and in fact I could measure a ~400ms regression on the worse case scenario (which happens when restarting Metro and re-transforming a Wilde from a warm local cache). I've benchmarked this regression and could find that it's caused by the array of `assetExtensions` (which is potentially large). I have a followup diff to improve this, which is able to remove the regression completely. Reviewed By: pvdz Differential Revision: D8695766 fbshipit-source-id: eccd18a4cbc91854f34d5c9ba7f95088f19483a1 --- jest/preprocessor.js | 1 + 1 file changed, 1 insertion(+) diff --git a/jest/preprocessor.js b/jest/preprocessor.js index 17838def4c2e86..c08d4a3cde7413 100644 --- a/jest/preprocessor.js +++ b/jest/preprocessor.js @@ -54,6 +54,7 @@ module.exports = { ast: true, // needed for open source (?) https://github.com/facebook/react-native/commit/f8d6b97140cffe8d18b2558f94570c8d1b410d5c#r28647044 dev: true, inlineRequires: true, + minify: false, platform: '', projectRoot: '', retainLines: true, From bdc0f3031a1ad77dc5056b9077bc9d301c6eee37 Mon Sep 17 00:00:00 2001 From: Rafael Oleza Date: Thu, 23 Aug 2018 15:44:48 -0700 Subject: [PATCH 098/273] Expose the actual transformer in the config Summary: This diff exposes the new more generic way to configure transformers in `Metro` via the config parameter `transformerPath`. The new generic transformers can be used to transform any kind of file, since they don't call any JS-specific method and their API is generic. They only need to implement a single `transform` method: ``` async function transform( absolutePath: string, relativePath: string, fileContents: Buffer, options: TransformOptions, // very soon these will be configurable ): Promise<{ output: Array, dependencies: Array<{ name: string, data: mixed, // very soon }>, }> { // ... } ``` Metro already had a `transformModulePath` config param, which was used to configure how babel was called in order to generate the AST. In order to avoid confusion, but keep the current open source transformer worker, I've renamed this param to `babelTransformerPath`. We can add a layer of compatibility and detect old config params in order to show a deprecation warning. Reviewed By: pvdz Differential Revision: D9070810 fbshipit-source-id: aebde879736026c09537f5d236eae24c06640abf --- local-cli/bundle/buildBundle.js | 4 ++-- local-cli/dependencies/dependencies.js | 6 +++--- local-cli/util/Config.js | 4 +++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/local-cli/bundle/buildBundle.js b/local-cli/bundle/buildBundle.js index cd31e21e0ded4d..426365a2612627 100644 --- a/local-cli/bundle/buildBundle.js +++ b/local-cli/bundle/buildBundle.js @@ -44,9 +44,9 @@ async function buildBundle( sourceMapUrl = path.basename(sourceMapUrl); } - config.transformModulePath = args.transformer + config.transformerPath = args.transformer ? path.resolve(args.transformer) - : config.transformModulePath; + : config.transformerPath; const requestOpts: RequestOptions = { entryFile: args.entryFile, diff --git a/local-cli/dependencies/dependencies.js b/local-cli/dependencies/dependencies.js index 6191548073ca98..e72293e646b08b 100644 --- a/local-cli/dependencies/dependencies.js +++ b/local-cli/dependencies/dependencies.js @@ -25,9 +25,9 @@ async function dependencies(argv, configPromise, args, packagerInstance) { } config.cacheStores = []; - config.transformModulePath = args.transformer - ? path.resolve(args.transformer) - : config.transformModulePath; + if (args.transformer) { + config.transformer.babelTransformerPath = path.resolve(args.transformer); + } const relativePath = path.relative( config.projectRoot, diff --git a/local-cli/util/Config.js b/local-cli/util/Config.js index d6d0134d133862..d6a8e24bec5a9d 100644 --- a/local-cli/util/Config.js +++ b/local-cli/util/Config.js @@ -76,8 +76,10 @@ const Config = { ], getPolyfills, }, + transformer: { + babelTransformerPath: require.resolve('metro/src/reactNativeTransformer'), + }, watchFolders: getWatchFolders(), - transformModulePath: require.resolve('metro/src/reactNativeTransformer'), }, async load(configFile: ?string): Promise { From a45a38368339755795197e11857b408aa87f70dd Mon Sep 17 00:00:00 2001 From: Hector Ramos Date: Fri, 24 Aug 2018 13:38:51 -0700 Subject: [PATCH 099/273] Revert "Expose the actual transformer in the config" This reverts commit bdc0f3031a1ad77dc5056b9077bc9d301c6eee37. --- local-cli/bundle/buildBundle.js | 4 ++-- local-cli/dependencies/dependencies.js | 6 +++--- local-cli/util/Config.js | 4 +--- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/local-cli/bundle/buildBundle.js b/local-cli/bundle/buildBundle.js index 426365a2612627..cd31e21e0ded4d 100644 --- a/local-cli/bundle/buildBundle.js +++ b/local-cli/bundle/buildBundle.js @@ -44,9 +44,9 @@ async function buildBundle( sourceMapUrl = path.basename(sourceMapUrl); } - config.transformerPath = args.transformer + config.transformModulePath = args.transformer ? path.resolve(args.transformer) - : config.transformerPath; + : config.transformModulePath; const requestOpts: RequestOptions = { entryFile: args.entryFile, diff --git a/local-cli/dependencies/dependencies.js b/local-cli/dependencies/dependencies.js index e72293e646b08b..6191548073ca98 100644 --- a/local-cli/dependencies/dependencies.js +++ b/local-cli/dependencies/dependencies.js @@ -25,9 +25,9 @@ async function dependencies(argv, configPromise, args, packagerInstance) { } config.cacheStores = []; - if (args.transformer) { - config.transformer.babelTransformerPath = path.resolve(args.transformer); - } + config.transformModulePath = args.transformer + ? path.resolve(args.transformer) + : config.transformModulePath; const relativePath = path.relative( config.projectRoot, diff --git a/local-cli/util/Config.js b/local-cli/util/Config.js index d6a8e24bec5a9d..d6d0134d133862 100644 --- a/local-cli/util/Config.js +++ b/local-cli/util/Config.js @@ -76,10 +76,8 @@ const Config = { ], getPolyfills, }, - transformer: { - babelTransformerPath: require.resolve('metro/src/reactNativeTransformer'), - }, watchFolders: getWatchFolders(), + transformModulePath: require.resolve('metro/src/reactNativeTransformer'), }, async load(configFile: ?string): Promise { From 50e95897d888c0f007d54fce7f0e846d2244c168 Mon Sep 17 00:00:00 2001 From: Hector Ramos Date: Fri, 24 Aug 2018 14:46:15 -0700 Subject: [PATCH 100/273] refactor publish workflow --- .circleci/config.yml | 83 ++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 49 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 67ebb9a4f3085d..ae0b587879edf7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -107,6 +107,13 @@ aliases: - /.*-stable/ - gh-pages + - &filter-only-tagged-releases + tags: + only: /v[0-9]+(\.[0-9]+)*(\-rc(\.[0-9]+)?)?/ + branches: + only: + - /.*-stable/ + # Dependency Management - &install-ndk name: Install Android NDK @@ -583,49 +590,16 @@ jobs: # Publishes new version onto npm # Only works on stable branches when a properly tagged commit is pushed - publish_npm_package: + publish: <<: *android_defaults steps: - - checkout - - - restore-cache: *restore-yarn-cache - - run: *yarn - - # Configure Android SDK and related dependencies - - run: *configure-android-path - - run: *install-android-build-dependencies - - - restore-cache: *restore-cache-android-packages - - run: *install-android-packages - - # Install Android NDK - - run: *create-ndk-directory - - restore-cache: *restore-cache-ndk - - run: *install-ndk - - # Fetch dependencies using Buck - - restore-cache: *restore-cache-downloads-buck - - run: *install-buck - - run: *download-dependencies-buck - - # Fetch dependencies using Gradle - - restore-cache: *restore-cache-downloads-gradle - - run: *download-dependencies-gradle - - - restore-cache: *restore-yarn-cache - - run: *yarn + - attach_workspace: + at: ~/react-native - run: name: Authenticate with npm command: echo "//registry.npmjs.org/:_authToken=${CIRCLE_NPM_TOKEN}" > ~/.npmrc - - run: - name: Authenticate git user - command: | - git config --global user.email "react-native-bot@users.noreply.github.com" - git config --global user.name "npm Deployment Script" - echo "machine github.com login react-native-bot password $GITHUB_TOKEN" > ~/.netrc - - run: name: Publish React Native Package command: node ./scripts/publish-npm.js @@ -673,19 +647,6 @@ workflows: requires: - checkout_code - # Only runs on vX.X.X tags if all tests are green - - publish_npm_package: - filters: - branches: - only: - - /.*-stable/ - tags: - only: /v[0-9]+(\.[0-9]+)*(\-rc(\.[0-9]+)?)?/ - requires: - - test_javascript - - test_objc - - test_android - # Only runs on PRs analyze: jobs: @@ -698,3 +659,27 @@ workflows: filters: *filter-ignore-master-stable requires: - checkout_code + + test-and-deploy: + jobs: + - checkout_code: + # required since `publish` has tag filters + filters: *filter-only-tagged-releases + - test_javascript: + requires: + - checkout_code + - test_objc: + requires: + - checkout_code + - test_android: + requires: + - checkout_code + + # Only runs on vX.X.X tags if all tests are green + - publish: + requires: + - test_javascript + - test_objc + - test_android + filters: *filter-only-tagged-releases + From a8aa8b673cbb477e41651eb61c62932c2a8b198c Mon Sep 17 00:00:00 2001 From: Hector Ramos Date: Fri, 24 Aug 2018 14:51:24 -0700 Subject: [PATCH 101/273] [0.57.0-rc.3] Bump version numbers --- Libraries/Core/ReactNativeVersion.js | 2 +- React/Base/RCTVersion.m | 2 +- ReactAndroid/gradle.properties | 2 +- .../facebook/react/modules/systeminfo/ReactNativeVersion.java | 2 +- package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Libraries/Core/ReactNativeVersion.js b/Libraries/Core/ReactNativeVersion.js index 478af88a7ba392..92bc60f7c3cf90 100644 --- a/Libraries/Core/ReactNativeVersion.js +++ b/Libraries/Core/ReactNativeVersion.js @@ -13,5 +13,5 @@ exports.version = { major: 0, minor: 57, patch: 0, - prerelease: 'rc.2', + prerelease: 'rc.3', }; diff --git a/React/Base/RCTVersion.m b/React/Base/RCTVersion.m index 8ec15ca95b0912..f59421c81f430a 100644 --- a/React/Base/RCTVersion.m +++ b/React/Base/RCTVersion.m @@ -23,7 +23,7 @@ static void __makeVersion() RCTVersionMajor: @(0), RCTVersionMinor: @(57), RCTVersionPatch: @(0), - RCTVersionPrerelease: @"rc.2", + RCTVersionPrerelease: @"rc.3", }; } diff --git a/ReactAndroid/gradle.properties b/ReactAndroid/gradle.properties index 838998a6dfe62c..0db23518d6c6bf 100644 --- a/ReactAndroid/gradle.properties +++ b/ReactAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=0.57.0-rc.2 +VERSION_NAME=0.57.0-rc.3 GROUP=com.facebook.react POM_NAME=ReactNative diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java index f5f8abf41d6d77..2500c2abc2ff46 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java @@ -18,5 +18,5 @@ public class ReactNativeVersion { "major", 0, "minor", 57, "patch", 0, - "prerelease", "rc.2"); + "prerelease", "rc.3"); } diff --git a/package.json b/package.json index 1c9e8f9171714e..e34277ed9cce06 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native", - "version": "0.57.0-rc.2", + "version": "0.57.0-rc.3", "description": "A framework for building native apps using React", "license": "MIT", "repository": { From 2fb77a9c1097e7b05d583e91a37981dfc7b6640f Mon Sep 17 00:00:00 2001 From: Rafael Oleza Date: Thu, 23 Aug 2018 15:44:48 -0700 Subject: [PATCH 102/273] Expose the actual transformer in the config Summary: This diff exposes the new more generic way to configure transformers in `Metro` via the config parameter `transformerPath`. The new generic transformers can be used to transform any kind of file, since they don't call any JS-specific method and their API is generic. They only need to implement a single `transform` method: ``` async function transform( absolutePath: string, relativePath: string, fileContents: Buffer, options: TransformOptions, // very soon these will be configurable ): Promise<{ output: Array, dependencies: Array<{ name: string, data: mixed, // very soon }>, }> { // ... } ``` Metro already had a `transformModulePath` config param, which was used to configure how babel was called in order to generate the AST. In order to avoid confusion, but keep the current open source transformer worker, I've renamed this param to `babelTransformerPath`. We can add a layer of compatibility and detect old config params in order to show a deprecation warning. Reviewed By: pvdz Differential Revision: D9070810 fbshipit-source-id: aebde879736026c09537f5d236eae24c06640abf --- local-cli/bundle/buildBundle.js | 4 ++-- local-cli/dependencies/dependencies.js | 6 +++--- local-cli/util/Config.js | 4 +++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/local-cli/bundle/buildBundle.js b/local-cli/bundle/buildBundle.js index cd31e21e0ded4d..426365a2612627 100644 --- a/local-cli/bundle/buildBundle.js +++ b/local-cli/bundle/buildBundle.js @@ -44,9 +44,9 @@ async function buildBundle( sourceMapUrl = path.basename(sourceMapUrl); } - config.transformModulePath = args.transformer + config.transformerPath = args.transformer ? path.resolve(args.transformer) - : config.transformModulePath; + : config.transformerPath; const requestOpts: RequestOptions = { entryFile: args.entryFile, diff --git a/local-cli/dependencies/dependencies.js b/local-cli/dependencies/dependencies.js index 6191548073ca98..e72293e646b08b 100644 --- a/local-cli/dependencies/dependencies.js +++ b/local-cli/dependencies/dependencies.js @@ -25,9 +25,9 @@ async function dependencies(argv, configPromise, args, packagerInstance) { } config.cacheStores = []; - config.transformModulePath = args.transformer - ? path.resolve(args.transformer) - : config.transformModulePath; + if (args.transformer) { + config.transformer.babelTransformerPath = path.resolve(args.transformer); + } const relativePath = path.relative( config.projectRoot, diff --git a/local-cli/util/Config.js b/local-cli/util/Config.js index d6d0134d133862..d6a8e24bec5a9d 100644 --- a/local-cli/util/Config.js +++ b/local-cli/util/Config.js @@ -76,8 +76,10 @@ const Config = { ], getPolyfills, }, + transformer: { + babelTransformerPath: require.resolve('metro/src/reactNativeTransformer'), + }, watchFolders: getWatchFolders(), - transformModulePath: require.resolve('metro/src/reactNativeTransformer'), }, async load(configFile: ?string): Promise { From 96939ad9f5e33e0d69e4e910fd0ea3e2056e8eb1 Mon Sep 17 00:00:00 2001 From: Rafael Oleza Date: Mon, 27 Aug 2018 19:24:49 -0700 Subject: [PATCH 103/273] Bump metro@0.44.0 Summary: shipit-splash Reviewed By: mjesun Differential Revision: D9504325 fbshipit-source-id: 191f27ee33c1363f180b0c6c710f65096e139df1 --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index e34277ed9cce06..08058097410ff7 100644 --- a/package.json +++ b/package.json @@ -170,10 +170,10 @@ "graceful-fs": "^4.1.3", "inquirer": "^3.0.6", "lodash": "^4.17.5", - "metro": "^0.43.6", - "metro-babel-register": "^0.43.6", - "metro-core": "^0.43.6", - "metro-memory-fs": "^0.43.6", + "metro": "^0.44.0", + "metro-babel-register": "^0.44.0", + "metro-core": "^0.44.0", + "metro-memory-fs": "^0.44.0", "mime": "^1.3.4", "minimist": "^1.2.0", "mkdirp": "^0.5.1", From a7d6a3b531b3547d930762b9e2738d1adacd90dd Mon Sep 17 00:00:00 2001 From: Rafael Oleza Date: Tue, 28 Aug 2018 18:51:15 -0700 Subject: [PATCH 104/273] Make the --transformer CLI argument override the babelTransformerPath Summary: D9070810 introduced a breaking change, making the `--transformer` CLI argument able to override the generic transformer instead of `babelTransformer`. Since we still have some scripts that assume `--transformer` is being used for overriding the babelTransformer path, we cannot do this breaking change yet, so this diff reverts the CLI handling to the old behaviour. Reviewed By: jrwats Differential Revision: D9550157 fbshipit-source-id: 8b4e26fcb5bca6e4b2f63b1e1a014bce23a31452 --- local-cli/bundle/buildBundle.js | 4 ---- local-cli/dependencies/dependencies.js | 3 --- 2 files changed, 7 deletions(-) diff --git a/local-cli/bundle/buildBundle.js b/local-cli/bundle/buildBundle.js index 426365a2612627..482fce1e634e38 100644 --- a/local-cli/bundle/buildBundle.js +++ b/local-cli/bundle/buildBundle.js @@ -44,10 +44,6 @@ async function buildBundle( sourceMapUrl = path.basename(sourceMapUrl); } - config.transformerPath = args.transformer - ? path.resolve(args.transformer) - : config.transformerPath; - const requestOpts: RequestOptions = { entryFile: args.entryFile, sourceMapUrl, diff --git a/local-cli/dependencies/dependencies.js b/local-cli/dependencies/dependencies.js index e72293e646b08b..c604c345d4d753 100644 --- a/local-cli/dependencies/dependencies.js +++ b/local-cli/dependencies/dependencies.js @@ -25,9 +25,6 @@ async function dependencies(argv, configPromise, args, packagerInstance) { } config.cacheStores = []; - if (args.transformer) { - config.transformer.babelTransformerPath = path.resolve(args.transformer); - } const relativePath = path.relative( config.projectRoot, From 9f83fccc3cb8194ffbedca6772e0d44cab0fe52b Mon Sep 17 00:00:00 2001 From: Rafael Oleza Date: Wed, 29 Aug 2018 10:47:33 -0700 Subject: [PATCH 105/273] Upgrade to babel@7.0.0 Summary: Now that babel7 is stable, we can upgrade Metro and fbsource to use it, yay!!!!! Reviewed By: mjesun Differential Revision: D9518571 fbshipit-source-id: c85569cb3058235f4f9310949897f7955ecf7324 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 08058097410ff7..d5f6c117269d1a 100644 --- a/package.json +++ b/package.json @@ -202,7 +202,7 @@ "yargs": "^9.0.0" }, "devDependencies": { - "@babel/core": "7.0.0-beta.56", + "@babel/core": "^7.0.0", "async": "^2.4.0", "babel-eslint": "9.0.0-beta.2", "babel-generator": "^6.26.0", From 7156c8662838bcf0225801289cb164890f56fc97 Mon Sep 17 00:00:00 2001 From: Rafael Oleza Date: Thu, 30 Aug 2018 03:22:17 -0700 Subject: [PATCH 106/273] End metro server gracefully when there are some edge errors Summary: This diff fixes a couple of edge cases that caused Metro to keep the process running when there were some specific errors (specially around the `dependencies` command and the transformer path). Reviewed By: jrwats Differential Revision: D9551834 fbshipit-source-id: 959cefcec9e2687dff89c94a871ae74c50d2dd77 --- local-cli/dependencies/dependencies.js | 41 ++++++++++++-------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/local-cli/dependencies/dependencies.js b/local-cli/dependencies/dependencies.js index c604c345d4d753..aba54ec1363b05 100644 --- a/local-cli/dependencies/dependencies.js +++ b/local-cli/dependencies/dependencies.js @@ -44,29 +44,26 @@ async function dependencies(argv, configPromise, args, packagerInstance) { ? fs.createWriteStream(args.output) : process.stdout; - return Promise.resolve( - (packagerInstance - ? packagerInstance.getOrderedDependencyPaths(options) - : Metro.getOrderedDependencyPaths(config, options) - ).then(deps => { - deps.forEach(modulePath => { - // Temporary hack to disable listing dependencies not under this directory. - // Long term, we need either - // (a) JS code to not depend on anything outside this directory, or - // (b) Come up with a way to declare this dependency in Buck. - const isInsideProjectRoots = - config.watchFolders.filter(root => modulePath.startsWith(root)) - .length > 0; + const deps = packagerInstance + ? await packagerInstance.getOrderedDependencyPaths(options) + : await Metro.getOrderedDependencyPaths(config, options); - if (isInsideProjectRoots) { - outStream.write(modulePath + '\n'); - } - }); - return writeToFile - ? denodeify(outStream.end).bind(outStream)() - : Promise.resolve(); - }), - ); + deps.forEach(modulePath => { + // Temporary hack to disable listing dependencies not under this directory. + // Long term, we need either + // (a) JS code to not depend on anything outside this directory, or + // (b) Come up with a way to declare this dependency in Buck. + const isInsideProjectRoots = + config.watchFolders.filter(root => modulePath.startsWith(root)).length > + 0; + + if (isInsideProjectRoots) { + outStream.write(modulePath + '\n'); + } + }); + return writeToFile + ? denodeify(outStream.end).bind(outStream)() + : Promise.resolve(); } module.exports = { From 1bfa422edbff6d355b823832b004e3134d221172 Mon Sep 17 00:00:00 2001 From: Rafael Oleza Date: Thu, 30 Aug 2018 03:22:19 -0700 Subject: [PATCH 107/273] Bump metro@0.45.0 Summary: shipitwithfiremissile Reviewed By: mjesun Differential Revision: D9558666 fbshipit-source-id: 1e4102de3986832ae86f56e5d245e0a0b6c4fa17 --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index d5f6c117269d1a..21bb3bae0bde3a 100644 --- a/package.json +++ b/package.json @@ -170,10 +170,10 @@ "graceful-fs": "^4.1.3", "inquirer": "^3.0.6", "lodash": "^4.17.5", - "metro": "^0.44.0", - "metro-babel-register": "^0.44.0", - "metro-core": "^0.44.0", - "metro-memory-fs": "^0.44.0", + "metro": "^0.45.0", + "metro-babel-register": "^0.45.0", + "metro-core": "^0.45.0", + "metro-memory-fs": "^0.45.0", "mime": "^1.3.4", "minimist": "^1.2.0", "mkdirp": "^0.5.1", From 6bcd51a3e9842741c548ac4b6e6a1c915d461f6f Mon Sep 17 00:00:00 2001 From: empyrical Date: Thu, 30 Aug 2018 16:19:38 -0700 Subject: [PATCH 108/273] Add support for out-of-tree platform plugins (#20825) Summary: This pull request adds the ability for a platform developer to provide a `"haste"` key under the `"rnpm"` key in their `package.json` which allows the packager to pick up that platform's javascript files. The intent is to remove the need to have custom platforms hardcoded in. This is inspired by the `"jest": { "haste": {} }` key used by jest. For example, React Native Dom would have an entry like: ```json { "rnpm": { "haste": { "providesModuleNodeModules": [ "react-native-dom" ], "platforms": [ "dom" ] } } } ``` Support for more keys (path blacklists perhaps?) could be added in the future. This succeeds #20662, as per a discussion I had with matthargett. I've got an open discussion over here as well: https://github.com/react-native-community/discussions-and-proposals/issues/21 Pull Request resolved: https://github.com/facebook/react-native/pull/20825 Differential Revision: D9596429 Pulled By: hramos fbshipit-source-id: a02f0da0bea8870bdc45d55e23da8ccbc36249f2 --- jest/__tests__/hasteImpl-test.js | 2 +- jest/hasteImpl.js | 29 ++++++++++---- local-cli/core/findPlugins.js | 67 +++++++++++++++++++++++--------- local-cli/core/index.js | 18 ++++++--- 4 files changed, 85 insertions(+), 31 deletions(-) diff --git a/jest/__tests__/hasteImpl-test.js b/jest/__tests__/hasteImpl-test.js index de493aa9a153da..ce2718f41eb1a5 100644 --- a/jest/__tests__/hasteImpl-test.js +++ b/jest/__tests__/hasteImpl-test.js @@ -32,7 +32,7 @@ it('returns the correct haste name for a RN library file', () => { }); it('returns the correct haste name for a file with a platform suffix', () => { - for (const platform of ['android', 'ios', 'native', 'web', 'windows']) { + for (const platform of ['android', 'ios', 'native']) { expect( getHasteName( getPath( diff --git a/jest/hasteImpl.js b/jest/hasteImpl.js index 030beeb9ea611a..9d1861bc9f2428 100644 --- a/jest/hasteImpl.js +++ b/jest/hasteImpl.js @@ -11,12 +11,25 @@ 'use strict'; const path = require('path'); +const findPlugins = require('../local-cli/core/findPlugins'); -const ROOTS = [ - path.resolve(__dirname, '..') + path.sep, - path.resolve(__dirname, '../../react-native-windows') + path.sep, - path.resolve(__dirname, '../../react-native-dom') + path.sep, -]; +const plugins = findPlugins([path.resolve(__dirname, '../../../')]); + +// Detect out-of-tree platforms and add them to the whitelists +const pluginRoots /*: Array< + string, +> */ = plugins.haste.providesModuleNodeModules.map( + name => path.resolve(__dirname, '../../', name) + path.sep, +); + +const pluginNameReducers /*: Array< + [RegExp, string], +> */ = plugins.haste.platforms.map(name => [ + new RegExp(`^(.*)\.(${name})$`), + '$1', +]); + +const ROOTS = [path.resolve(__dirname, '..') + path.sep, ...pluginRoots]; const BLACKLISTED_PATTERNS /*: Array */ = [ /.*[\\\/]__(mocks|tests)__[\\\/].*/, @@ -36,8 +49,10 @@ const NAME_REDUCERS /*: Array<[RegExp, string]> */ = [ [/^(?:.*[\\\/])?([a-zA-Z0-9$_.-]+)$/, '$1'], // strip .js/.js.flow suffix [/^(.*)\.js(\.flow)?$/, '$1'], - // strip .android/.ios/.native/.web suffix - [/^(.*)\.(android|ios|native|web|windows|dom)$/, '$1'], + // strip platform suffix + [/^(.*)\.(android|ios|native)$/, '$1'], + // strip plugin platform suffixes + ...pluginNameReducers, ]; const haste = { diff --git a/local-cli/core/findPlugins.js b/local-cli/core/findPlugins.js index 595577ba8e875c..6c23c5d9f279a5 100644 --- a/local-cli/core/findPlugins.js +++ b/local-cli/core/findPlugins.js @@ -47,11 +47,37 @@ const findPlatformsInPackage = pjson => { return path.join(pjson.name, pjson.rnpm.platform); }; +const getEmptyPluginConfig = () => ({ + commands: [], + platforms: [], + haste: { + platforms: [], + providesModuleNodeModules: [], + }, +}); + +const findHasteConfigInPackageAndConcat = (pjson, haste) => { + if (!pjson.rnpm || !pjson.rnpm.haste) { + return; + } + let pkgHaste = pjson.rnpm.haste; + + if (pkgHaste.platforms) { + haste.platforms = haste.platforms.concat(pkgHaste.platforms); + } + + if (pkgHaste.providesModuleNodeModules) { + haste.providesModuleNodeModules = haste.providesModuleNodeModules.concat( + pkgHaste.providesModuleNodeModules, + ); + } +}; + const findPluginInFolder = folder => { const pjson = readPackage(folder); if (!pjson) { - return {commands: [], platforms: []}; + return getEmptyPluginConfig(); } const deps = union( @@ -59,24 +85,23 @@ const findPluginInFolder = folder => { Object.keys(pjson.devDependencies || {}), ); - return deps.reduce( - (acc, pkg) => { - let commands = acc.commands; - let platforms = acc.platforms; - if (isRNPMPlugin(pkg)) { - commands = commands.concat(pkg); - } - if (isReactNativePlugin(pkg)) { - const pkgJson = readPackage(path.join(folder, 'node_modules', pkg)); - if (pkgJson) { - commands = commands.concat(findPluginsInReactNativePackage(pkgJson)); - platforms = platforms.concat(findPlatformsInPackage(pkgJson)); - } + return deps.reduce((acc, pkg) => { + let commands = acc.commands; + let platforms = acc.platforms; + let haste = acc.haste; + if (isRNPMPlugin(pkg)) { + commands = commands.concat(pkg); + } + if (isReactNativePlugin(pkg)) { + const pkgJson = readPackage(path.join(folder, 'node_modules', pkg)); + if (pkgJson) { + commands = commands.concat(findPluginsInReactNativePackage(pkgJson)); + platforms = platforms.concat(findPlatformsInPackage(pkgJson)); + findHasteConfigInPackageAndConcat(pkgJson, haste); } - return {commands: commands, platforms: platforms}; - }, - {commands: [], platforms: []}, - ); + } + return {commands: commands, platforms: platforms, haste: haste}; + }, getEmptyPluginConfig()); }; /** @@ -89,5 +114,11 @@ module.exports = function findPlugins(folders) { return { commands: uniq(flatten(plugins.map(p => p.commands))), platforms: uniq(flatten(plugins.map(p => p.platforms))), + haste: { + platforms: uniq(flatten(plugins.map(p => p.haste.platforms))), + providesModuleNodeModules: uniq( + flatten(plugins.map(p => p.haste.providesModuleNodeModules)), + ), + }, }; }; diff --git a/local-cli/core/index.js b/local-cli/core/index.js index 7027706250a4c1..2e66b662bd5299 100644 --- a/local-cli/core/index.js +++ b/local-cli/core/index.js @@ -70,11 +70,11 @@ const defaultConfig = { hasteImplModulePath: require.resolve('../../jest/hasteImpl'), getPlatforms(): Array { - return ['ios', 'android', 'windows', 'web', 'dom']; + return ['ios', 'android', 'native', ...plugins.haste.platforms]; }, getProvidesModuleNodeModules(): Array { - return ['react-native', 'react-native-windows', 'react-native-dom']; + return ['react-native', ...plugins.haste.providesModuleNodeModules]; }, }; @@ -132,9 +132,17 @@ async function getCliConfig(): Promise { ); config.transformer.assetRegistryPath = ASSET_REGISTRY_PATH; - config.resolver.hasteImplModulePath = config.resolver.hasteImplModulePath || defaultConfig.hasteImplModulePath; - config.resolver.platforms = config.resolver.platforms || defaultConfig.getPlatforms(); - config.resolver.providesModuleNodeModules = config.resolver.providesModuleNodeModules || defaultConfig.getProvidesModuleNodeModules(); + config.resolver.hasteImplModulePath = + config.resolver.hasteImplModulePath || defaultConfig.hasteImplModulePath; + config.resolver.platforms = config.resolver.platforms + ? config.resolver.platforms.concat(defaultConfig.getPlatforms()) + : defaultConfig.getPlatforms(); + config.resolver.providesModuleNodeModules = config.resolver + .providesModuleNodeModules + ? config.resolver.providesModuleNodeModules.concat( + defaultConfig.getProvidesModuleNodeModules(), + ) + : defaultConfig.getProvidesModuleNodeModules(); return {...defaultRNConfig, ...config}; } From a3b2f5d05ffaa4fd931a288828e1f6618fac5763 Mon Sep 17 00:00:00 2001 From: Kevin Gozali Date: Tue, 14 Aug 2018 18:14:27 -0700 Subject: [PATCH 109/273] iOS downgrade error to warning when invoking native module with invalid bridge Summary: A bunch of flows including JS reload and e2e tests seem to hit the race condition, causing redbox. For now, make it a warning to unblock. Differential Revision: D9327418 fbshipit-source-id: a72b378d88f7566268fd9415fbd34225c8b931e7 --- React/CxxModule/RCTNativeModule.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/React/CxxModule/RCTNativeModule.mm b/React/CxxModule/RCTNativeModule.mm index 8cf3b74db431cc..00a03b37d9759a 100644 --- a/React/CxxModule/RCTNativeModule.mm +++ b/React/CxxModule/RCTNativeModule.mm @@ -79,8 +79,8 @@ dispatch_async(queue, block); } } else { - RCTLogError(@"Attempted to invoke `%u` (method ID) on `%@` (NativeModule name) with an invalid bridge.", - methodId, m_moduleData.name); + RCTLogWarn(@"Attempted to invoke `%u` (method ID) on `%@` (NativeModule name) with an invalid bridge.", + methodId, m_moduleData.name); } } From ef7e99c1bbc7f3a99093961bc5e7717c9e45dc79 Mon Sep 17 00:00:00 2001 From: Oleg Lokhvitsky Date: Thu, 30 Aug 2018 12:59:33 -0700 Subject: [PATCH 110/273] ScrollView snapToOffsets Summary: * Added snapToOffsets prop to ScrollView. Allows snapping at arbitrary points. * Fixed pagingEnabled not being overridden by snapToInterval on iOS. * Fixed Android *requiring* pagingEnabled to be defined alongside snapToInterval. * Added support for decelerationRate on Android. * Fixed snapping implementation. It was not calculating end position correctly at all (velocity is not a linear offset). * Resolves https://github.com/facebook/react-native/issues/20155 * Added support for new content being added during scroll (mirrors existing functionality in vertical ScrollView). * Added support for snapToInterval. * Resolves https://github.com/facebook/react-native/issues/19552 Reviewed By: yungsters Differential Revision: D9405703 fbshipit-source-id: b3c367b8079e6810794b0165dfdbcff4abff2eda --- Libraries/Components/ScrollView/ScrollView.js | 55 ++-- .../ScrollView/processDecelerationRate.js | 17 +- React/Views/ScrollView/RCTScrollView.h | 1 + React/Views/ScrollView/RCTScrollView.m | 72 ++++- React/Views/ScrollView/RCTScrollViewManager.m | 1 + .../scroll/ReactHorizontalScrollView.java | 256 +++++++++++++++-- .../ReactHorizontalScrollViewManager.java | 17 ++ .../react/views/scroll/ReactScrollView.java | 272 +++++++++++++++--- .../views/scroll/ReactScrollViewManager.java | 35 ++- 9 files changed, 634 insertions(+), 92 deletions(-) diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js index 9f0688e87489f3..00235546eafba1 100644 --- a/Libraries/Components/ScrollView/ScrollView.js +++ b/Libraries/Components/ScrollView/ScrollView.js @@ -125,19 +125,6 @@ type IOSProps = $ReadOnly<{| * @platform ios */ centerContent?: ?boolean, - /** - * A floating-point number that determines how quickly the scroll view - * decelerates after the user lifts their finger. You may also use string - * shortcuts `"normal"` and `"fast"` which match the underlying iOS settings - * for `UIScrollViewDecelerationRateNormal` and - * `UIScrollViewDecelerationRateFast` respectively. - * - * - `'normal'`: 0.998 (the default) - * - `'fast'`: 0.99 - * - * @platform ios - */ - decelerationRate?: ?('fast' | 'normal' | number), /** * The style of the scroll indicators. * @@ -353,6 +340,17 @@ export type Props = $ReadOnly<{| * ``` */ contentContainerStyle?: ?ViewStyleProp, + /** + * A floating-point number that determines how quickly the scroll view + * decelerates after the user lifts their finger. You may also use string + * shortcuts `"normal"` and `"fast"` which match the underlying iOS settings + * for `UIScrollViewDecelerationRateNormal` and + * `UIScrollViewDecelerationRateFast` respectively. + * + * - `'normal'`: 0.998 on iOS, 0.985 on Android (the default) + * - `'fast'`: 0.99 on iOS, 0.9 on Android + */ + decelerationRate?: ?('fast' | 'normal' | number), /** * When true, the scroll view's children are arranged horizontally in a row * instead of vertically in a column. The default value is false. @@ -462,12 +460,20 @@ export type Props = $ReadOnly<{| * When set, causes the scroll view to stop at multiples of the value of * `snapToInterval`. This can be used for paginating through children * that have lengths smaller than the scroll view. Typically used in - * combination with `snapToAlignment` and `decelerationRate="fast"` on ios. - * Overrides less configurable `pagingEnabled` prop. + * combination with `snapToAlignment` and `decelerationRate="fast"`. * - * Supported for horizontal scrollview on android. + * Overrides less configurable `pagingEnabled` prop. */ snapToInterval?: ?number, + /** + * When set, causes the scroll view to stop at the defined offsets. + * This can be used for paginating through variously sized children + * that have lengths smaller than the scroll view. Typically used in + * combination with `decelerationRate="fast"`. + * + * Overrides less configurable `pagingEnabled` and `snapToInterval` props. + */ + snapToOffsets?: ?$ReadOnlyArray, /** * Experimental: When true, offscreen child views (whose `overflow` value is * `hidden`) are removed from their native backing superview when offscreen. @@ -773,10 +779,6 @@ const ScrollView = createReactClass({ } else { ScrollViewClass = RCTScrollView; ScrollContentContainerViewClass = RCTScrollContentView; - warning( - this.props.snapToInterval == null || !this.props.pagingEnabled, - 'snapToInterval is currently ignored when pagingEnabled is true.', - ); } invariant( @@ -920,6 +922,19 @@ const ScrollView = createReactClass({ ? true : false, DEPRECATED_sendUpdatedChildFrames, + // pagingEnabled is overridden by snapToInterval / snapToOffsets + pagingEnabled: Platform.select({ + // on iOS, pagingEnabled must be set to false to have snapToInterval / snapToOffsets work + ios: + this.props.pagingEnabled && + this.props.snapToInterval == null && + this.props.snapToOffsets == null, + // on Android, pagingEnabled must be set to true to have snapToInterval / snapToOffsets work + android: + this.props.pagingEnabled || + this.props.snapToInterval != null || + this.props.snapToOffsets != null, + }), }; const {decelerationRate} = this.props; diff --git a/Libraries/Components/ScrollView/processDecelerationRate.js b/Libraries/Components/ScrollView/processDecelerationRate.js index 18b903ffa3831c..fc50c6766f92e9 100644 --- a/Libraries/Components/ScrollView/processDecelerationRate.js +++ b/Libraries/Components/ScrollView/processDecelerationRate.js @@ -5,15 +5,26 @@ * LICENSE file in the root directory of this source tree. * * @format + * @flow */ 'use strict'; -function processDecelerationRate(decelerationRate) { +const Platform = require('Platform'); + +function processDecelerationRate( + decelerationRate: number | 'normal' | 'fast', +): number { if (decelerationRate === 'normal') { - decelerationRate = 0.998; + return Platform.select({ + ios: 0.998, + android: 0.985, + }); } else if (decelerationRate === 'fast') { - decelerationRate = 0.99; + return Platform.select({ + ios: 0.99, + android: 0.9, + }); } return decelerationRate; } diff --git a/React/Views/ScrollView/RCTScrollView.h b/React/Views/ScrollView/RCTScrollView.h index e1853e5d9d3558..688d8f62e771d3 100644 --- a/React/Views/ScrollView/RCTScrollView.h +++ b/React/Views/ScrollView/RCTScrollView.h @@ -45,6 +45,7 @@ @property (nonatomic, assign) BOOL centerContent; @property (nonatomic, copy) NSDictionary *maintainVisibleContentPosition; @property (nonatomic, assign) int snapToInterval; +@property (nonatomic, copy) NSArray *snapToOffsets; @property (nonatomic, copy) NSString *snapToAlignment; // NOTE: currently these event props are only declared so we can export the diff --git a/React/Views/ScrollView/RCTScrollView.m b/React/Views/ScrollView/RCTScrollView.m index 4afdb379d4a0de..5d5f947d0e6f62 100644 --- a/React/Views/ScrollView/RCTScrollView.m +++ b/React/Views/ScrollView/RCTScrollView.m @@ -727,12 +727,72 @@ - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { - // snapToInterval - // An alternative to enablePaging which allows setting custom stopping intervals, - // smaller than a full page size. Often seen in apps which feature horizonally - // scrolling items. snapToInterval does not enforce scrolling one interval at a time - // but guarantees that the scroll will stop at an interval point. - if (self.snapToInterval) { + if (self.snapToOffsets) { + // An alternative to enablePaging and snapToInterval which allows setting custom + // stopping points that don't have to be the same distance apart. Often seen in + // apps which feature horizonally scrolling items. snapToInterval does not enforce + // scrolling one interval at a time but guarantees that the scroll will stop at + // a snap offset point. + + // Find which axis to snap + BOOL isHorizontal = [self isHorizontal:scrollView]; + + // Calculate maximum content offset + CGSize viewportSize = [self _calculateViewportSize]; + CGFloat maximumOffset = isHorizontal + ? MAX(0, _scrollView.contentSize.width - viewportSize.width) + : MAX(0, _scrollView.contentSize.height - viewportSize.height); + + // Calculate the snap offsets adjacent to the initial offset target + CGFloat targetOffset = isHorizontal ? targetContentOffset->x : targetContentOffset->y; + CGFloat smallerOffset = 0.0; + CGFloat largerOffset = maximumOffset; + + for (int i = 0; i < self.snapToOffsets.count; i++) { + CGFloat offset = [[self.snapToOffsets objectAtIndex:i] floatValue]; + + if (offset <= targetOffset) { + if (targetOffset - offset < targetOffset - smallerOffset) { + smallerOffset = offset; + } + } + + if (offset >= targetOffset) { + if (offset - targetOffset < largerOffset - targetOffset) { + largerOffset = offset; + } + } + } + + // Calculate the nearest offset + CGFloat nearestOffset = targetOffset - smallerOffset < largerOffset - targetOffset + ? smallerOffset + : largerOffset; + + // Chose the correct snap offset based on velocity + CGFloat velocityAlongAxis = isHorizontal ? velocity.x : velocity.y; + if (velocityAlongAxis > 0.0) { + targetOffset = largerOffset; + } else if (velocityAlongAxis < 0.0) { + targetOffset = smallerOffset; + } else { + targetOffset = nearestOffset; + } + + // Make sure the new offset isn't out of bounds + targetOffset = MIN(MAX(0, targetOffset), maximumOffset); + + // Set new targetContentOffset + if (isHorizontal) { + targetContentOffset->x = targetOffset; + } else { + targetContentOffset->y = targetOffset; + } + } else if (self.snapToInterval) { + // An alternative to enablePaging which allows setting custom stopping intervals, + // smaller than a full page size. Often seen in apps which feature horizonally + // scrolling items. snapToInterval does not enforce scrolling one interval at a time + // but guarantees that the scroll will stop at an interval point. CGFloat snapToIntervalF = (CGFloat)self.snapToInterval; // Find which axis to snap diff --git a/React/Views/ScrollView/RCTScrollViewManager.m b/React/Views/ScrollView/RCTScrollViewManager.m index e5824afd3f386d..c03f2ccd8c45c7 100644 --- a/React/Views/ScrollView/RCTScrollViewManager.m +++ b/React/Views/ScrollView/RCTScrollViewManager.m @@ -81,6 +81,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(contentInset, UIEdgeInsets) RCT_EXPORT_VIEW_PROPERTY(scrollIndicatorInsets, UIEdgeInsets) RCT_EXPORT_VIEW_PROPERTY(snapToInterval, int) +RCT_EXPORT_VIEW_PROPERTY(snapToOffsets, NSArray) RCT_EXPORT_VIEW_PROPERTY(snapToAlignment, NSString) RCT_REMAP_VIEW_PROPERTY(contentOffset, scrollView.contentOffset, CGPoint) RCT_EXPORT_VIEW_PROPERTY(onScrollBeginDrag, RCTDirectEventBlock) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java index ba6ff876c2b7dd..f544aafdb66db6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java @@ -11,15 +11,20 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; -import android.support.v4.view.ViewCompat; import android.graphics.drawable.LayerDrawable; +import android.graphics.Rect; +import android.hardware.SensorManager; +import android.support.v4.view.ViewCompat; +import android.support.v4.text.TextUtilsCompat; import android.util.Log; import android.view.MotionEvent; import android.view.View; +import android.view.ViewConfiguration; import android.widget.HorizontalScrollView; +import android.widget.OverScroller; + import com.facebook.infer.annotation.Assertions; import com.facebook.react.common.ReactConstants; import com.facebook.react.uimanager.MeasureSpecAssertions; @@ -27,6 +32,10 @@ import com.facebook.react.uimanager.ReactClippingViewGroupHelper; import com.facebook.react.uimanager.events.NativeGestureUtil; import com.facebook.react.views.view.ReactViewBackgroundManager; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.Locale; import javax.annotation.Nullable; /** @@ -36,7 +45,11 @@ public class ReactHorizontalScrollView extends HorizontalScrollView implements ReactClippingViewGroup { + private static @Nullable Field sScrollerField; + private static boolean sTriedToGetScrollerField = false; + private final OnScrollDispatchHelper mOnScrollDispatchHelper = new OnScrollDispatchHelper(); + private final @Nullable OverScroller mScroller; private final VelocityHelper mVelocityHelper = new VelocityHelper(); private final Rect mRect = new Rect(); @@ -53,6 +66,8 @@ public class ReactHorizontalScrollView extends HorizontalScrollView implements private @Nullable Drawable mEndBackground; private int mEndFillColor = Color.TRANSPARENT; private int mSnapInterval = 0; + private float mDecelerationRate = 0.985f; + private @Nullable List mSnapOffsets; private ReactViewBackgroundManager mReactBackgroundManager; public ReactHorizontalScrollView(Context context) { @@ -63,6 +78,47 @@ public ReactHorizontalScrollView(Context context, @Nullable FpsListener fpsListe super(context); mReactBackgroundManager = new ReactViewBackgroundManager(this); mFpsListener = fpsListener; + + mScroller = getOverScrollerFromParent(); + } + + @Nullable + private OverScroller getOverScrollerFromParent() { + OverScroller scroller; + + if (!sTriedToGetScrollerField) { + sTriedToGetScrollerField = true; + try { + sScrollerField = HorizontalScrollView.class.getDeclaredField("mScroller"); + sScrollerField.setAccessible(true); + } catch (NoSuchFieldException e) { + Log.w( + ReactConstants.TAG, + "Failed to get mScroller field for HorizontalScrollView! " + + "This app will exhibit the bounce-back scrolling bug :("); + } + } + + if (sScrollerField != null) { + try { + Object scrollerValue = sScrollerField.get(this); + if (scrollerValue instanceof OverScroller) { + scroller = (OverScroller) scrollerValue; + } else { + Log.w( + ReactConstants.TAG, + "Failed to cast mScroller field in HorizontalScrollView (probably due to OEM changes to AOSP)! " + + "This app will exhibit the bounce-back scrolling bug :("); + scroller = null; + } + } catch (IllegalAccessException e) { + throw new RuntimeException("Failed to get mScroller from HorizontalScrollView!", e); + } + } else { + scroller = null; + } + + return scroller; } public void setScrollPerfTag(@Nullable String scrollPerfTag) { @@ -95,10 +151,22 @@ public void setPagingEnabled(boolean pagingEnabled) { mPagingEnabled = pagingEnabled; } + public void setDecelerationRate(float decelerationRate) { + mDecelerationRate = decelerationRate; + + if (mScroller != null) { + mScroller.setFriction(1.0f - mDecelerationRate); + } + } + public void setSnapInterval(int snapInterval) { mSnapInterval = snapInterval; } + public void setSnapOffsets(List snapOffsets) { + mSnapOffsets = snapOffsets; + } + public void flashScrollIndicators() { awakenScrollBars(); } @@ -194,7 +262,34 @@ public boolean onTouchEvent(MotionEvent ev) { @Override public void fling(int velocityX) { if (mPagingEnabled) { - smoothScrollToPage(velocityX); + smoothScrollAndSnap(velocityX); + } else if (mScroller != null) { + // FB SCROLLVIEW CHANGE + + // We provide our own version of fling that uses a different call to the standard OverScroller + // which takes into account the possibility of adding new content while the ScrollView is + // animating. Because we give essentially no max X for the fling, the fling will continue as long + // as there is content. See #onOverScrolled() to see the second part of this change which properly + // aborts the scroller animation when we get to the bottom of the ScrollView content. + + int scrollWindowWidth = getWidth() - getPaddingStart() - getPaddingEnd(); + + mScroller.fling( + getScrollX(), // startX + getScrollY(), // startY + velocityX, // velocityX + 0, // velocityY + 0, // minX + Integer.MAX_VALUE, // maxX + 0, // minY + 0, // maxY + scrollWindowWidth / 2, // overX + 0 // overY + ); + + ViewCompat.postInvalidateOnAnimation(this); + + // END FB SCROLLVIEW CHANGE } else { super.fling(velocityX); } @@ -251,6 +346,28 @@ public void setEndFillColor(int color) { } } + @Override + protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) { + if (mScroller != null) { + // FB SCROLLVIEW CHANGE + + // This is part two of the reimplementation of fling to fix the bounce-back bug. See #fling() for + // more information. + + if (!mScroller.isFinished() && mScroller.getCurrX() != mScroller.getFinalX()) { + int scrollRange = computeHorizontalScrollRange() - getWidth(); + if (scrollX >= scrollRange) { + mScroller.abortAnimation(); + scrollX = scrollRange; + } + } + + // END FB SCROLLVIEW CHANGE + } + + super.onOverScrolled(scrollX, scrollY, clampedX, clampedY); + } + private void enableFpsListener() { if (isScrollPerfLoggingEnabled()) { Assertions.assertNotNull(mFpsListener); @@ -290,7 +407,7 @@ public void draw(Canvas canvas) { * runnable that checks if we scrolled in the last frame and if so assumes we are still scrolling. */ private void handlePostTouchScrolling(int velocityX, int velocityY) { - // If we aren't going to do anything (send events or snap to page), we can early out. + // If we aren't going to do anything (send events or snap to page), we can early exit out. if (!mSendMomentumEvents && !mPagingEnabled && !isScrollPerfLoggingEnabled()) { return; } @@ -323,7 +440,7 @@ public void run() { // Only if we have pagingEnabled and we have not snapped to the page do we // need to continue checking for the scroll. And we cause that scroll by asking for it mSnappingToPage = true; - smoothScrollToPage(0); + smoothScrollAndSnap(0); ViewCompat.postOnAnimationDelayed(ReactHorizontalScrollView.this, this, ReactScrollViewHelper.MOMENTUM_DELAY); @@ -343,21 +460,124 @@ public void run() { } /** - * This will smooth scroll us to the nearest page boundary - * It currently just looks at where the content is relative to the page and slides to the nearest - * page. It is intended to be run after we are done scrolling, and handling any momentum - * scrolling. + * This will smooth scroll us to the nearest snap offset point + * It currently just looks at where the content is and slides to the nearest point. + * It is intended to be run after we are done scrolling, and handling any momentum scrolling. */ - private void smoothScrollToPage(int velocity) { - int width = getSnapInterval(); - int currentX = getScrollX(); - // TODO (t11123799) - Should we do anything beyond linear accounting of the velocity - int predictedX = currentX + velocity; - int page = currentX / width; - if (predictedX > page * width + width / 2) { - page = page + 1; + private void smoothScrollAndSnap(int velocityX) { + if (getChildCount() <= 0) { + return; + } + + int maximumOffset = Math.max(0, computeHorizontalScrollRange() - getWidth()); + int targetOffset = 0; + int smallerOffset = 0; + int largerOffset = maximumOffset; + + // ScrollView can *only* scroll for 250ms when using smoothScrollTo and there's + // no way to customize the scroll duration. So, we create a temporary OverScroller + // so we can predict where a fling would land and snap to nearby that point. + OverScroller scroller = new OverScroller(getContext()); + scroller.setFriction(1.0f - mDecelerationRate); + + // predict where a fling would end up so we can scroll to the nearest snap offset + int width = getWidth() - getPaddingStart() - getPaddingEnd(); + scroller.fling( + getScrollX(), // startX + getScrollY(), // startY + velocityX, // velocityX + 0, // velocityY + 0, // minX + maximumOffset, // maxX + 0, // minY + 0, // maxY + width/2, // overX + 0 // overY + ); + targetOffset = scroller.getFinalX(); + + // offsets are from the right edge in RTL layouts + boolean isRTL = TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL; + if (isRTL) { + targetOffset = maximumOffset - targetOffset; + velocityX = -velocityX; + } + + // get the nearest snap points to the target offset + if (mSnapOffsets != null) { + for (int i = 0; i < mSnapOffsets.size(); i ++) { + int offset = mSnapOffsets.get(i); + + if (offset <= targetOffset) { + if (targetOffset - offset < targetOffset - smallerOffset) { + smallerOffset = offset; + } + } + + if (offset >= targetOffset) { + if (offset - targetOffset < largerOffset - targetOffset) { + largerOffset = offset; + } + } + } + } else { + double interval = (double) getSnapInterval(); + double ratio = (double) targetOffset / interval; + smallerOffset = (int) (Math.floor(ratio) * interval); + largerOffset = (int) (Math.ceil(ratio) * interval); + } + + // Calculate the nearest offset + int nearestOffset = targetOffset - smallerOffset < largerOffset - targetOffset + ? smallerOffset + : largerOffset; + + // Chose the correct snap offset based on velocity + if (velocityX > 0) { + targetOffset = largerOffset; + } else if (velocityX < 0) { + targetOffset = smallerOffset; + } else { + targetOffset = nearestOffset; + } + + // Make sure the new offset isn't out of bounds + targetOffset = Math.min(Math.max(0, targetOffset), maximumOffset); + + if (isRTL) { + targetOffset = maximumOffset - targetOffset; + velocityX = -velocityX; + } + + // smoothScrollTo will always scroll over 250ms which is often *waaay* + // too short and will cause the scrolling to feel almost instant + // try to manually interact with OverScroller instead + // if velocity is 0 however, fling() won't work, so we want to use smoothScrollTo + if (mScroller != null) { + mActivelyScrolling = true; + + mScroller.fling( + getScrollX(), // startX + getScrollY(), // startY + // velocity = 0 doesn't work with fling() so we pretend there's a reasonable + // initial velocity going on when a touch is released without any movement + velocityX != 0 ? velocityX : targetOffset - getScrollX(), // velocityX + 0, // velocityY + // setting both minX and maxX to the same value will guarantee that we scroll to it + // but using the standard fling-style easing rather than smoothScrollTo's 250ms animation + targetOffset, // minX + targetOffset, // maxX + 0, // minY + 0, // maxY + // we only want to allow overscrolling if the final offset is at the very edge of the view + (targetOffset == 0 || targetOffset == maximumOffset) ? width / 2 : 0, // overX + 0 // overY + ); + + postInvalidateOnAnimation(); + } else { + smoothScrollTo(targetOffset, getScrollY()); } - smoothScrollTo(page * width, getScrollY()); } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java index e6536a6e53eb76..2f65a7c8922579 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java @@ -24,6 +24,8 @@ import com.facebook.react.uimanager.annotations.ReactPropGroup; import com.facebook.yoga.YogaConstants; +import java.util.ArrayList; +import java.util.List; import javax.annotation.Nullable; /** @@ -73,6 +75,11 @@ public void setShowsHorizontalScrollIndicator(ReactHorizontalScrollView view, bo view.setHorizontalScrollBarEnabled(value); } + @ReactProp(name = "decelerationRate") + public void setDecelerationRate(ReactHorizontalScrollView view, float decelerationRate) { + view.setDecelerationRate(decelerationRate); + } + @ReactProp(name = "snapToInterval") public void setSnapToInterval(ReactHorizontalScrollView view, float snapToInterval) { // snapToInterval needs to be exposed as a float because of the Javascript interface. @@ -80,6 +87,16 @@ public void setSnapToInterval(ReactHorizontalScrollView view, float snapToInterv view.setSnapInterval((int) (snapToInterval * screenDisplayMetrics.density)); } + @ReactProp(name = "snapToOffsets") + public void setSnapToOffsets(ReactHorizontalScrollView view, @Nullable ReadableArray snapToOffsets) { + DisplayMetrics screenDisplayMetrics = DisplayMetricsHolder.getScreenDisplayMetrics(); + List offsets = new ArrayList(); + for (int i = 0; i < snapToOffsets.size(); i++) { + offsets.add((int) (snapToOffsets.getDouble(i) * screenDisplayMetrics.density)); + } + view.setSnapOffsets(offsets); + } + @ReactProp(name = ReactClippingViewGroupHelper.PROP_REMOVE_CLIPPED_SUBVIEWS) public void setRemoveClippedSubviews(ReactHorizontalScrollView view, boolean removeClippedSubviews) { view.setRemoveClippedSubviews(removeClippedSubviews); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index 57b401cd6fbf5c..9df87e57e7404f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -20,6 +20,7 @@ import android.view.ViewGroup; import android.widget.OverScroller; import android.widget.ScrollView; + import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.ReactContext; import com.facebook.react.common.ReactConstants; @@ -28,7 +29,9 @@ import com.facebook.react.uimanager.ReactClippingViewGroupHelper; import com.facebook.react.uimanager.events.NativeGestureUtil; import com.facebook.react.views.view.ReactViewBackgroundManager; + import java.lang.reflect.Field; +import java.util.List; import javax.annotation.Nullable; /** @@ -49,10 +52,11 @@ public class ReactScrollView extends ScrollView implements ReactClippingViewGrou private final VelocityHelper mVelocityHelper = new VelocityHelper(); private final Rect mRect = new Rect(); // for reuse to avoid allocation + private boolean mActivelyScrolling; private @Nullable Rect mClippingRect; - private boolean mDoneFlinging; private boolean mDragging; - private boolean mFlinging; + private boolean mPagingEnabled = false; + private @Nullable Runnable mPostTouchRunnable; private boolean mRemoveClippedSubviews; private boolean mScrollEnabled = true; private boolean mSendMomentumEvents; @@ -60,6 +64,9 @@ public class ReactScrollView extends ScrollView implements ReactClippingViewGrou private @Nullable String mScrollPerfTag; private @Nullable Drawable mEndBackground; private int mEndFillColor = Color.TRANSPARENT; + private int mSnapInterval = 0; + private float mDecelerationRate = 0.985f; + private @Nullable List mSnapOffsets; private View mContentView; private ReactViewBackgroundManager mReactBackgroundManager; @@ -128,6 +135,26 @@ public void setScrollEnabled(boolean scrollEnabled) { mScrollEnabled = scrollEnabled; } + public void setPagingEnabled(boolean pagingEnabled) { + mPagingEnabled = pagingEnabled; + } + + public void setDecelerationRate(float decelerationRate) { + mDecelerationRate = decelerationRate; + + if (mScroller != null) { + mScroller.setFriction(1.0f - mDecelerationRate); + } + } + + public void setSnapInterval(int snapInterval) { + mSnapInterval = snapInterval; + } + + public void setSnapOffsets(List snapOffsets) { + mSnapOffsets = snapOffsets; + } + public void flashScrollIndicators() { awakenScrollBars(); } @@ -167,15 +194,13 @@ protected void onAttachedToWindow() { protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); + mActivelyScrolling = true; + if (mOnScrollDispatchHelper.onScrollChanged(x, y)) { if (mRemoveClippedSubviews) { updateClippingRect(); } - if (mFlinging) { - mDoneFlinging = false; - } - ReactScrollViewHelper.emitScrollEvent( this, mOnScrollDispatchHelper.getXFlingVelocity(), @@ -216,12 +241,16 @@ public boolean onTouchEvent(MotionEvent ev) { mVelocityHelper.calculateVelocity(ev); int action = ev.getAction() & MotionEvent.ACTION_MASK; if (action == MotionEvent.ACTION_UP && mDragging) { + float velocityX = mVelocityHelper.getXVelocity(); + float velocityY = mVelocityHelper.getYVelocity(); ReactScrollViewHelper.emitScrollEndDragEvent( this, - mVelocityHelper.getXVelocity(), - mVelocityHelper.getYVelocity()); + velocityX, + velocityY); mDragging = false; - disableFpsListener(); + // After the touch finishes, we may need to do some scrolling afterwards either as a result + // of a fling or because we need to page align the content + handlePostTouchScrolling(Math.round(velocityX), Math.round(velocityY)); } return super.onTouchEvent(ev); @@ -263,7 +292,9 @@ public void getClippingRect(Rect outClippingRect) { @Override public void fling(int velocityY) { - if (mScroller != null) { + if (mPagingEnabled) { + smoothScrollAndSnap(velocityY); + } else if (mScroller != null) { // FB SCROLLVIEW CHANGE // We provide our own version of fling that uses a different call to the standard OverScroller @@ -275,16 +306,17 @@ public void fling(int velocityY) { int scrollWindowHeight = getHeight() - getPaddingBottom() - getPaddingTop(); mScroller.fling( - getScrollX(), - getScrollY(), - 0, - velocityY, - 0, - 0, - 0, - Integer.MAX_VALUE, - 0, - scrollWindowHeight / 2); + getScrollX(), // startX + getScrollY(), // startY + 0, // velocityX + velocityY, // velocityY + 0, // minX + 0, // maxX + 0, // minY + Integer.MAX_VALUE, // maxY + 0, // overX + scrollWindowHeight / 2 // overY + ); ViewCompat.postInvalidateOnAnimation(this); @@ -292,29 +324,7 @@ public void fling(int velocityY) { } else { super.fling(velocityY); } - - if (mSendMomentumEvents || isScrollPerfLoggingEnabled()) { - mFlinging = true; - enableFpsListener(); - ReactScrollViewHelper.emitScrollMomentumBeginEvent(this, 0, velocityY); - Runnable r = new Runnable() { - @Override - public void run() { - if (mDoneFlinging) { - mFlinging = false; - disableFpsListener(); - ReactScrollViewHelper.emitScrollMomentumEndEvent(ReactScrollView.this); - } else { - mDoneFlinging = true; - ViewCompat.postOnAnimationDelayed( - ReactScrollView.this, - this, - ReactScrollViewHelper.MOMENTUM_DELAY); - } - } - }; - ViewCompat.postOnAnimationDelayed(this, r, ReactScrollViewHelper.MOMENTUM_DELAY); - } + handlePostTouchScrolling(0, velocityY); } private void enableFpsListener() { @@ -357,6 +367,182 @@ public void draw(Canvas canvas) { super.draw(canvas); } + /** + * This handles any sort of scrolling that may occur after a touch is finished. This may be + * momentum scrolling (fling) or because you have pagingEnabled on the scroll view. Because we + * don't get any events from Android about this lifecycle, we do all our detection by creating a + * runnable that checks if we scrolled in the last frame and if so assumes we are still scrolling. + */ + private void handlePostTouchScrolling(int velocityX, int velocityY) { + // If we aren't going to do anything (send events or snap to page), we can early exit out. + if (!mSendMomentumEvents && !mPagingEnabled && !isScrollPerfLoggingEnabled()) { + return; + } + + // Check if we are already handling this which may occur if this is called by both the touch up + // and a fling call + if (mPostTouchRunnable != null) { + return; + } + + if (mSendMomentumEvents) { + enableFpsListener(); + ReactScrollViewHelper.emitScrollMomentumBeginEvent(this, velocityX, velocityY); + } + + mActivelyScrolling = false; + mPostTouchRunnable = new Runnable() { + + private boolean mSnappingToPage = false; + + @Override + public void run() { + if (mActivelyScrolling) { + // We are still scrolling so we just post to check again a frame later + mActivelyScrolling = false; + ViewCompat.postOnAnimationDelayed(ReactScrollView.this, + this, + ReactScrollViewHelper.MOMENTUM_DELAY); + } else { + if (mPagingEnabled && !mSnappingToPage) { + // Only if we have pagingEnabled and we have not snapped to the page do we + // need to continue checking for the scroll. And we cause that scroll by asking for it + mSnappingToPage = true; + smoothScrollAndSnap(0); + ViewCompat.postOnAnimationDelayed(ReactScrollView.this, + this, + ReactScrollViewHelper.MOMENTUM_DELAY); + } else { + if (mSendMomentumEvents) { + ReactScrollViewHelper.emitScrollMomentumEndEvent(ReactScrollView.this); + } + ReactScrollView.this.mPostTouchRunnable = null; + disableFpsListener(); + } + } + } + }; + ViewCompat.postOnAnimationDelayed(ReactScrollView.this, + mPostTouchRunnable, + ReactScrollViewHelper.MOMENTUM_DELAY); + } + + /** + * This will smooth scroll us to the nearest snap offset point + * It currently just looks at where the content is and slides to the nearest point. + * It is intended to be run after we are done scrolling, and handling any momentum scrolling. + */ + private void smoothScrollAndSnap(int velocityY) { + if (getChildCount() <= 0) { + return; + } + + int maximumOffset = getMaxScrollY(); + int targetOffset = 0; + int smallerOffset = 0; + int largerOffset = maximumOffset; + + // ScrollView can *only* scroll for 250ms when using smoothScrollTo and there's + // no way to customize the scroll duration. So, we create a temporary OverScroller + // so we can predict where a fling would land and snap to nearby that point. + OverScroller scroller = new OverScroller(getContext()); + scroller.setFriction(1.0f - mDecelerationRate); + + // predict where a fling would end up so we can scroll to the nearest snap offset + int height = getHeight() - getPaddingBottom() - getPaddingTop(); + scroller.fling( + getScrollX(), // startX + getScrollY(), // startY + 0, // velocityX + velocityY, // velocityY + 0, // minX + 0, // maxX + 0, // minY + maximumOffset, // maxY + 0, // overX + height/2 // overY + ); + targetOffset = scroller.getFinalY(); + + // get the nearest snap points to the target offset + if (mSnapOffsets != null) { + for (int i = 0; i < mSnapOffsets.size(); i ++) { + int offset = mSnapOffsets.get(i); + + if (offset <= targetOffset) { + if (targetOffset - offset < targetOffset - smallerOffset) { + smallerOffset = offset; + } + } + + if (offset >= targetOffset) { + if (offset - targetOffset < largerOffset - targetOffset) { + largerOffset = offset; + } + } + } + } else { + double interval = (double) getSnapInterval(); + double ratio = (double) targetOffset / interval; + smallerOffset = (int) (Math.floor(ratio) * interval); + largerOffset = (int) (Math.ceil(ratio) * interval); + } + + // Calculate the nearest offset + int nearestOffset = targetOffset - smallerOffset < largerOffset - targetOffset + ? smallerOffset + : largerOffset; + + // Chose the correct snap offset based on velocity + if (velocityY > 0) { + targetOffset = largerOffset; + } else if (velocityY < 0) { + targetOffset = smallerOffset; + } else { + targetOffset = nearestOffset; + } + + // Make sure the new offset isn't out of bounds + targetOffset = Math.min(Math.max(0, targetOffset), maximumOffset); + + // smoothScrollTo will always scroll over 250ms which is often *waaay* + // too short and will cause the scrolling to feel almost instant + // try to manually interact with OverScroller instead + // if velocity is 0 however, fling() won't work, so we want to use smoothScrollTo + if (mScroller != null) { + mActivelyScrolling = true; + + mScroller.fling( + getScrollX(), // startX + getScrollY(), // startY + // velocity = 0 doesn't work with fling() so we pretend there's a reasonable + // initial velocity going on when a touch is released without any movement + 0, // velocityX + velocityY != 0 ? velocityY : targetOffset - getScrollY(), // velocityY + 0, // minX + 0, // maxX + // setting both minY and maxY to the same value will guarantee that we scroll to it + // but using the standard fling-style easing rather than smoothScrollTo's 250ms animation + targetOffset, // minY + targetOffset, // maxY + 0, // overX + // we only want to allow overscrolling if the final offset is at the very edge of the view + (targetOffset == 0 || targetOffset == maximumOffset) ? height / 2 : 0 // overY + ); + + postInvalidateOnAnimation(); + } else { + smoothScrollTo(getScrollX(), targetOffset); + } + } + + private int getSnapInterval() { + if (mSnapInterval != 0) { + return mSnapInterval; + } + return getHeight(); + } + public void setEndFillColor(int color) { if (color != mEndFillColor) { mEndFillColor = color; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java index df520b5e4669f4..413b825ec9f5ec 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java @@ -10,10 +10,12 @@ import android.annotation.TargetApi; import android.graphics.Color; import android.support.v4.view.ViewCompat; +import android.util.DisplayMetrics; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.common.MapBuilder; import com.facebook.react.module.annotations.ReactModule; +import com.facebook.react.uimanager.DisplayMetricsHolder; import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.ReactClippingViewGroupHelper; import com.facebook.react.uimanager.Spacing; @@ -24,13 +26,15 @@ import com.facebook.react.uimanager.annotations.ReactPropGroup; import com.facebook.yoga.YogaConstants; -import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import javax.annotation.Nullable; /** * View manager for {@link ReactScrollView} components. * - *

Note that {@link ReactScrollView} and {@link ReactHorizontalScrollView} are exposed to JS + *

Note that {@link ReactScrollView} and {@link ReactScrollView} are exposed to JS * as a single ScrollView component, configured via the {@code horizontal} boolean property. */ @TargetApi(11) @@ -75,6 +79,28 @@ public void setShowsVerticalScrollIndicator(ReactScrollView view, boolean value) view.setVerticalScrollBarEnabled(value); } + @ReactProp(name = "decelerationRate") + public void setDecelerationRate(ReactScrollView view, float decelerationRate) { + view.setDecelerationRate(decelerationRate); + } + + @ReactProp(name = "snapToInterval") + public void setSnapToInterval(ReactScrollView view, float snapToInterval) { + // snapToInterval needs to be exposed as a float because of the Javascript interface. + DisplayMetrics screenDisplayMetrics = DisplayMetricsHolder.getScreenDisplayMetrics(); + view.setSnapInterval((int) (snapToInterval * screenDisplayMetrics.density)); + } + + @ReactProp(name = "snapToOffsets") + public void setSnapToOffsets(ReactScrollView view, @Nullable ReadableArray snapToOffsets) { + DisplayMetrics screenDisplayMetrics = DisplayMetricsHolder.getScreenDisplayMetrics(); + List offsets = new ArrayList(); + for (int i = 0; i < snapToOffsets.size(); i++) { + offsets.add((int) (snapToOffsets.getDouble(i) * screenDisplayMetrics.density)); + } + view.setSnapOffsets(offsets); + } + @ReactProp(name = ReactClippingViewGroupHelper.PROP_REMOVE_CLIPPED_SUBVIEWS) public void setRemoveClippedSubviews(ReactScrollView view, boolean removeClippedSubviews) { view.setRemoveClippedSubviews(removeClippedSubviews); @@ -105,6 +131,11 @@ public void setScrollPerfTag(ReactScrollView view, @Nullable String scrollPerfTa view.setScrollPerfTag(scrollPerfTag); } + @ReactProp(name = "pagingEnabled") + public void setPagingEnabled(ReactScrollView view, boolean pagingEnabled) { + view.setPagingEnabled(pagingEnabled); + } + /** * When set, fills the rest of the scrollview with a color to avoid setting a background and * creating unnecessary overdraw. From af554aabe738218b6a37bbe7725529d4a1e470ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Wed, 22 Aug 2018 23:20:05 -0700 Subject: [PATCH 111/273] Update CircleCI confih --- .circleci/config.yml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ae0b587879edf7..e89c2ce451dae7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -593,13 +593,26 @@ jobs: publish: <<: *android_defaults steps: - - attach_workspace: - at: ~/react-native + - checkout + + - restore-cache: *restore-yarn-cache + - run: *yarn - run: name: Authenticate with npm command: echo "//registry.npmjs.org/:_authToken=${CIRCLE_NPM_TOKEN}" > ~/.npmrc + - run: + name: Authenticate with npm + command: echo "//registry.npmjs.org/:_authToken=${CIRCLE_NPM_TOKEN}" > ~/.npmrc + + - run: + name: Authenticate git user + command: | + git config --global user.email "react-native-bot@users.noreply.github.com" + git config --global user.name "npm Deployment Script" + echo "machine github.com login react-native-bot password $GITHUB_TOKEN" > ~/.netrc + - run: name: Publish React Native Package command: node ./scripts/publish-npm.js From 6d4970f886caaa6863ecf521a786412647000dd9 Mon Sep 17 00:00:00 2001 From: Mike Grabowski Date: Sun, 2 Sep 2018 19:13:46 +0200 Subject: [PATCH 112/273] [0.57.0-rc.4] Bump version numbers --- Libraries/Core/ReactNativeVersion.js | 2 +- React/Base/RCTVersion.m | 2 +- ReactAndroid/gradle.properties | 2 +- .../facebook/react/modules/systeminfo/ReactNativeVersion.java | 2 +- package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Libraries/Core/ReactNativeVersion.js b/Libraries/Core/ReactNativeVersion.js index 92bc60f7c3cf90..f29a91f582c6ca 100644 --- a/Libraries/Core/ReactNativeVersion.js +++ b/Libraries/Core/ReactNativeVersion.js @@ -13,5 +13,5 @@ exports.version = { major: 0, minor: 57, patch: 0, - prerelease: 'rc.3', + prerelease: 'rc.4', }; diff --git a/React/Base/RCTVersion.m b/React/Base/RCTVersion.m index f59421c81f430a..d3cbd0481e1154 100644 --- a/React/Base/RCTVersion.m +++ b/React/Base/RCTVersion.m @@ -23,7 +23,7 @@ static void __makeVersion() RCTVersionMajor: @(0), RCTVersionMinor: @(57), RCTVersionPatch: @(0), - RCTVersionPrerelease: @"rc.3", + RCTVersionPrerelease: @"rc.4", }; } diff --git a/ReactAndroid/gradle.properties b/ReactAndroid/gradle.properties index 0db23518d6c6bf..2c70bc5d009dcd 100644 --- a/ReactAndroid/gradle.properties +++ b/ReactAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=0.57.0-rc.3 +VERSION_NAME=0.57.0-rc.4 GROUP=com.facebook.react POM_NAME=ReactNative diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java index 2500c2abc2ff46..308b0328bd26dd 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java @@ -18,5 +18,5 @@ public class ReactNativeVersion { "major", 0, "minor", 57, "patch", 0, - "prerelease", "rc.3"); + "prerelease", "rc.4"); } diff --git a/package.json b/package.json index 21bb3bae0bde3a..e4297b6513242b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native", - "version": "0.57.0-rc.3", + "version": "0.57.0-rc.4", "description": "A framework for building native apps using React", "license": "MIT", "repository": { From f28a6bbc4415b62ab9193f778a02fb702539fd9e Mon Sep 17 00:00:00 2001 From: Mike Grabowski Date: Mon, 3 Sep 2018 11:06:17 +0200 Subject: [PATCH 113/273] Revert "[0.57.0-rc.4] Bump version numbers" This reverts commit 6d4970f886caaa6863ecf521a786412647000dd9. --- Libraries/Core/ReactNativeVersion.js | 2 +- React/Base/RCTVersion.m | 2 +- ReactAndroid/gradle.properties | 2 +- .../facebook/react/modules/systeminfo/ReactNativeVersion.java | 2 +- package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Libraries/Core/ReactNativeVersion.js b/Libraries/Core/ReactNativeVersion.js index f29a91f582c6ca..92bc60f7c3cf90 100644 --- a/Libraries/Core/ReactNativeVersion.js +++ b/Libraries/Core/ReactNativeVersion.js @@ -13,5 +13,5 @@ exports.version = { major: 0, minor: 57, patch: 0, - prerelease: 'rc.4', + prerelease: 'rc.3', }; diff --git a/React/Base/RCTVersion.m b/React/Base/RCTVersion.m index d3cbd0481e1154..f59421c81f430a 100644 --- a/React/Base/RCTVersion.m +++ b/React/Base/RCTVersion.m @@ -23,7 +23,7 @@ static void __makeVersion() RCTVersionMajor: @(0), RCTVersionMinor: @(57), RCTVersionPatch: @(0), - RCTVersionPrerelease: @"rc.4", + RCTVersionPrerelease: @"rc.3", }; } diff --git a/ReactAndroid/gradle.properties b/ReactAndroid/gradle.properties index 2c70bc5d009dcd..0db23518d6c6bf 100644 --- a/ReactAndroid/gradle.properties +++ b/ReactAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=0.57.0-rc.4 +VERSION_NAME=0.57.0-rc.3 GROUP=com.facebook.react POM_NAME=ReactNative diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java index 308b0328bd26dd..2500c2abc2ff46 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java @@ -18,5 +18,5 @@ public class ReactNativeVersion { "major", 0, "minor", 57, "patch", 0, - "prerelease", "rc.4"); + "prerelease", "rc.3"); } diff --git a/package.json b/package.json index e4297b6513242b..21bb3bae0bde3a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native", - "version": "0.57.0-rc.4", + "version": "0.57.0-rc.3", "description": "A framework for building native apps using React", "license": "MIT", "repository": { From 4382413e5b2a234a35c26f3a23a7a3bc2218a2e5 Mon Sep 17 00:00:00 2001 From: Mike Grabowski Date: Mon, 3 Sep 2018 11:06:53 +0200 Subject: [PATCH 114/273] Fix flow --- .flowconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.flowconfig b/.flowconfig index 0bd9289ffb57bc..946bf93e165281 100644 --- a/.flowconfig +++ b/.flowconfig @@ -23,7 +23,7 @@ .*/Libraries/polyfills/.* ; Ignore metro -.*/node_modules/metro/.* +; .*/node_modules/metro/.* ; These should not be required directly ; require from fbjs/lib instead: require('fbjs/lib/invariant') From 9974d4f1e7019ff7e157460caff0355bf5ed6cef Mon Sep 17 00:00:00 2001 From: Mike Grabowski Date: Mon, 3 Sep 2018 11:07:32 +0200 Subject: [PATCH 115/273] [0.57.0-rc.4] Bump version numbers --- Libraries/Core/ReactNativeVersion.js | 2 +- React/Base/RCTVersion.m | 2 +- ReactAndroid/gradle.properties | 2 +- .../facebook/react/modules/systeminfo/ReactNativeVersion.java | 2 +- package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Libraries/Core/ReactNativeVersion.js b/Libraries/Core/ReactNativeVersion.js index 92bc60f7c3cf90..f29a91f582c6ca 100644 --- a/Libraries/Core/ReactNativeVersion.js +++ b/Libraries/Core/ReactNativeVersion.js @@ -13,5 +13,5 @@ exports.version = { major: 0, minor: 57, patch: 0, - prerelease: 'rc.3', + prerelease: 'rc.4', }; diff --git a/React/Base/RCTVersion.m b/React/Base/RCTVersion.m index f59421c81f430a..d3cbd0481e1154 100644 --- a/React/Base/RCTVersion.m +++ b/React/Base/RCTVersion.m @@ -23,7 +23,7 @@ static void __makeVersion() RCTVersionMajor: @(0), RCTVersionMinor: @(57), RCTVersionPatch: @(0), - RCTVersionPrerelease: @"rc.3", + RCTVersionPrerelease: @"rc.4", }; } diff --git a/ReactAndroid/gradle.properties b/ReactAndroid/gradle.properties index 0db23518d6c6bf..2c70bc5d009dcd 100644 --- a/ReactAndroid/gradle.properties +++ b/ReactAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=0.57.0-rc.3 +VERSION_NAME=0.57.0-rc.4 GROUP=com.facebook.react POM_NAME=ReactNative diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java index 2500c2abc2ff46..308b0328bd26dd 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java @@ -18,5 +18,5 @@ public class ReactNativeVersion { "major", 0, "minor", 57, "patch", 0, - "prerelease", "rc.3"); + "prerelease", "rc.4"); } diff --git a/package.json b/package.json index 21bb3bae0bde3a..e4297b6513242b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native", - "version": "0.57.0-rc.3", + "version": "0.57.0-rc.4", "description": "A framework for building native apps using React", "license": "MIT", "repository": { From 0943c6437afa625d911cf02f0d7d6aa27b9f399b Mon Sep 17 00:00:00 2001 From: Hector Ramos Date: Thu, 6 Sep 2018 15:27:10 -0700 Subject: [PATCH 116/273] Sync Circle CI config from master --- .circleci/config.yml | 122 ++++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 66 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e89c2ce451dae7..475c3a676e23be 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -107,13 +107,6 @@ aliases: - /.*-stable/ - gh-pages - - &filter-only-tagged-releases - tags: - only: /v[0-9]+(\.[0-9]+)*(\-rc(\.[0-9]+)?)?/ - branches: - only: - - /.*-stable/ - # Dependency Management - &install-ndk name: Install Android NDK @@ -466,11 +459,9 @@ jobs: - run: name: Build iOS app for simulator command: yarn run build-ios-e2e - # TODO: Fix these failing tests. - - run: *display-broken-tests-warning - run: - name: Run Detox Tests (Disabled) - command: ./scripts/circleci/exec_author_check.sh yarn run test-ios-e2e + name: Run Detox Tests + command: yarn run test-ios-e2e # Set up an Android environment for downstream jobs test_android: @@ -548,49 +539,48 @@ jobs: # Issues will be posted to the PR itself via GitHub bots. # This workflow should only fail if the bots fail to run. analyze_pr: - <<: *js_defaults + <<: *defaults + docker: + - image: circleci/node:10 + environment: + - PATH: "/opt/yarn/yarn-v1.5.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" steps: - - attach_workspace: - at: ~/react-native + - checkout + - run: *setup-artifacts - - restore-cache: *restore-cache-analysis + - restore-cache: *restore-yarn-cache - run: *yarn + - run: - name: Install Additional Dependencies + name: Analyze Code command: | + # GITHUB_TOKEN=eslint-bot public_repo access token if [ -n "$CIRCLE_PR_NUMBER" ]; then - yarn add github@0.2.4 - cd bots - yarn install --non-interactive --cache-folder ~/.cache/yarn + echo -e "\\x1B[36mInstalling additional dependencies\\x1B[0m"; yarn add @octokit/rest@15.10.0 + echo -e "\\x1B[36mAnalyzing code\\x1B[0m"; GITHUB_TOKEN="af6ef0d15709bc91d""06a6217a5a826a226fb57b7" ./scripts/circleci/analyze_code.sh else - echo "Skipping dependency installation." + echo "Skipping code analysis." fi - - save-cache: *save-cache-analysis + when: always + - restore-cache: *restore-cache-analysis - run: name: Analyze Pull Request command: | # DANGER_GITHUB_API_TOKEN=React-Linter public_repo access token if [ -n "$CIRCLE_PR_NUMBER" ]; then - cd bots && DANGER_GITHUB_API_TOKEN="80aa64c50f38a267e9ba""575d41d528f9c234edb8" yarn danger + cd bots + yarn install --non-interactive --cache-folder ~/.cache/yarn + DANGER_GITHUB_API_TOKEN="80aa64c50f38a267e9ba""575d41d528f9c234edb8" yarn danger else echo "Skipping pull request analysis." fi when: always - - run: - name: Analyze Code - command: | - # GITHUB_TOKEN=eslint-bot public_repo access token - if [ -n "$CIRCLE_PR_NUMBER" ]; then - GITHUB_TOKEN="af6ef0d15709bc91d""06a6217a5a826a226fb57b7" CI_USER=$CIRCLE_PROJECT_USERNAME CI_REPO=$CIRCLE_PROJECT_REPONAME PULL_REQUEST_NUMBER=$CIRCLE_PR_NUMBER scripts/circleci/analyze_code.sh - else - echo "Skipping code analysis." - fi - when: always + - save-cache: *save-cache-analysis # Publishes new version onto npm # Only works on stable branches when a properly tagged commit is pushed - publish: + publish_npm_package: <<: *android_defaults steps: - checkout @@ -598,9 +588,29 @@ jobs: - restore-cache: *restore-yarn-cache - run: *yarn - - run: - name: Authenticate with npm - command: echo "//registry.npmjs.org/:_authToken=${CIRCLE_NPM_TOKEN}" > ~/.npmrc + # Configure Android SDK and related dependencies + - run: *configure-android-path + - run: *install-android-build-dependencies + + - restore-cache: *restore-cache-android-packages + - run: *install-android-packages + + # Install Android NDK + - run: *create-ndk-directory + - restore-cache: *restore-cache-ndk + - run: *install-ndk + + # Fetch dependencies using Buck + - restore-cache: *restore-cache-downloads-buck + - run: *install-buck + - run: *download-dependencies-buck + + # Fetch dependencies using Gradle + - restore-cache: *restore-cache-downloads-gradle + - run: *download-dependencies-gradle + + - restore-cache: *restore-yarn-cache + - run: *yarn - run: name: Authenticate with npm @@ -660,39 +670,19 @@ workflows: requires: - checkout_code - # Only runs on PRs - analyze: - jobs: - # Checkout repo and run Yarn - - checkout_code: - filters: *filter-ignore-master-stable - - # Run code checks - - analyze_pr: - filters: *filter-ignore-master-stable - requires: - - checkout_code - - test-and-deploy: - jobs: - - checkout_code: - # required since `publish` has tag filters - filters: *filter-only-tagged-releases - - test_javascript: - requires: - - checkout_code - - test_objc: - requires: - - checkout_code - - test_android: - requires: - - checkout_code - # Only runs on vX.X.X tags if all tests are green - - publish: + - publish_npm_package: + filters: + branches: + only: + - /.*-stable/ + tags: + only: /v[0-9]+(\.[0-9]+)*(\-rc(\.[0-9]+)?)?/ requires: - test_javascript - test_objc - test_android - filters: *filter-only-tagged-releases + # Run code checks + - analyze_pr: + filters: *filter-ignore-master-stable From 5ffa4b319bea239b61b3aa41625b02b046049334 Mon Sep 17 00:00:00 2001 From: Hector Ramos Date: Thu, 6 Sep 2018 15:28:49 -0700 Subject: [PATCH 117/273] Revert "[0.57.0-rc.4] Bump version numbers" This reverts commit 9974d4f1e7019ff7e157460caff0355bf5ed6cef. --- Libraries/Core/ReactNativeVersion.js | 2 +- React/Base/RCTVersion.m | 2 +- ReactAndroid/gradle.properties | 2 +- .../facebook/react/modules/systeminfo/ReactNativeVersion.java | 2 +- package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Libraries/Core/ReactNativeVersion.js b/Libraries/Core/ReactNativeVersion.js index f29a91f582c6ca..92bc60f7c3cf90 100644 --- a/Libraries/Core/ReactNativeVersion.js +++ b/Libraries/Core/ReactNativeVersion.js @@ -13,5 +13,5 @@ exports.version = { major: 0, minor: 57, patch: 0, - prerelease: 'rc.4', + prerelease: 'rc.3', }; diff --git a/React/Base/RCTVersion.m b/React/Base/RCTVersion.m index d3cbd0481e1154..f59421c81f430a 100644 --- a/React/Base/RCTVersion.m +++ b/React/Base/RCTVersion.m @@ -23,7 +23,7 @@ static void __makeVersion() RCTVersionMajor: @(0), RCTVersionMinor: @(57), RCTVersionPatch: @(0), - RCTVersionPrerelease: @"rc.4", + RCTVersionPrerelease: @"rc.3", }; } diff --git a/ReactAndroid/gradle.properties b/ReactAndroid/gradle.properties index 2c70bc5d009dcd..0db23518d6c6bf 100644 --- a/ReactAndroid/gradle.properties +++ b/ReactAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=0.57.0-rc.4 +VERSION_NAME=0.57.0-rc.3 GROUP=com.facebook.react POM_NAME=ReactNative diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java index 308b0328bd26dd..2500c2abc2ff46 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java @@ -18,5 +18,5 @@ public class ReactNativeVersion { "major", 0, "minor", 57, "patch", 0, - "prerelease", "rc.4"); + "prerelease", "rc.3"); } diff --git a/package.json b/package.json index e4297b6513242b..21bb3bae0bde3a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native", - "version": "0.57.0-rc.4", + "version": "0.57.0-rc.3", "description": "A framework for building native apps using React", "license": "MIT", "repository": { From 9dcc39586c867021a21836e0ccbd96d6283a3099 Mon Sep 17 00:00:00 2001 From: Hector Ramos Date: Thu, 6 Sep 2018 15:28:55 -0700 Subject: [PATCH 118/273] [0.57.0-rc.4] Bump version numbers --- Libraries/Core/ReactNativeVersion.js | 2 +- React/Base/RCTVersion.m | 2 +- ReactAndroid/gradle.properties | 2 +- .../facebook/react/modules/systeminfo/ReactNativeVersion.java | 2 +- package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Libraries/Core/ReactNativeVersion.js b/Libraries/Core/ReactNativeVersion.js index 92bc60f7c3cf90..f29a91f582c6ca 100644 --- a/Libraries/Core/ReactNativeVersion.js +++ b/Libraries/Core/ReactNativeVersion.js @@ -13,5 +13,5 @@ exports.version = { major: 0, minor: 57, patch: 0, - prerelease: 'rc.3', + prerelease: 'rc.4', }; diff --git a/React/Base/RCTVersion.m b/React/Base/RCTVersion.m index f59421c81f430a..d3cbd0481e1154 100644 --- a/React/Base/RCTVersion.m +++ b/React/Base/RCTVersion.m @@ -23,7 +23,7 @@ static void __makeVersion() RCTVersionMajor: @(0), RCTVersionMinor: @(57), RCTVersionPatch: @(0), - RCTVersionPrerelease: @"rc.3", + RCTVersionPrerelease: @"rc.4", }; } diff --git a/ReactAndroid/gradle.properties b/ReactAndroid/gradle.properties index 0db23518d6c6bf..2c70bc5d009dcd 100644 --- a/ReactAndroid/gradle.properties +++ b/ReactAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=0.57.0-rc.3 +VERSION_NAME=0.57.0-rc.4 GROUP=com.facebook.react POM_NAME=ReactNative diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java index 2500c2abc2ff46..308b0328bd26dd 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java @@ -18,5 +18,5 @@ public class ReactNativeVersion { "major", 0, "minor", 57, "patch", 0, - "prerelease", "rc.3"); + "prerelease", "rc.4"); } diff --git a/package.json b/package.json index 21bb3bae0bde3a..e4297b6513242b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native", - "version": "0.57.0-rc.3", + "version": "0.57.0-rc.4", "description": "A framework for building native apps using React", "license": "MIT", "repository": { From cb471c7b3e6bc5c53a7e76ab3dc07d1998edd01e Mon Sep 17 00:00:00 2001 From: Hector Ramos Date: Thu, 6 Sep 2018 16:12:06 -0700 Subject: [PATCH 119/273] Revert "[0.57.0-rc.4] Bump version numbers" This reverts commit 9dcc39586c867021a21836e0ccbd96d6283a3099. --- Libraries/Core/ReactNativeVersion.js | 2 +- React/Base/RCTVersion.m | 2 +- ReactAndroid/gradle.properties | 2 +- .../facebook/react/modules/systeminfo/ReactNativeVersion.java | 2 +- package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Libraries/Core/ReactNativeVersion.js b/Libraries/Core/ReactNativeVersion.js index f29a91f582c6ca..92bc60f7c3cf90 100644 --- a/Libraries/Core/ReactNativeVersion.js +++ b/Libraries/Core/ReactNativeVersion.js @@ -13,5 +13,5 @@ exports.version = { major: 0, minor: 57, patch: 0, - prerelease: 'rc.4', + prerelease: 'rc.3', }; diff --git a/React/Base/RCTVersion.m b/React/Base/RCTVersion.m index d3cbd0481e1154..f59421c81f430a 100644 --- a/React/Base/RCTVersion.m +++ b/React/Base/RCTVersion.m @@ -23,7 +23,7 @@ static void __makeVersion() RCTVersionMajor: @(0), RCTVersionMinor: @(57), RCTVersionPatch: @(0), - RCTVersionPrerelease: @"rc.4", + RCTVersionPrerelease: @"rc.3", }; } diff --git a/ReactAndroid/gradle.properties b/ReactAndroid/gradle.properties index 2c70bc5d009dcd..0db23518d6c6bf 100644 --- a/ReactAndroid/gradle.properties +++ b/ReactAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=0.57.0-rc.4 +VERSION_NAME=0.57.0-rc.3 GROUP=com.facebook.react POM_NAME=ReactNative diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java index 308b0328bd26dd..2500c2abc2ff46 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java @@ -18,5 +18,5 @@ public class ReactNativeVersion { "major", 0, "minor", 57, "patch", 0, - "prerelease", "rc.4"); + "prerelease", "rc.3"); } diff --git a/package.json b/package.json index e4297b6513242b..21bb3bae0bde3a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native", - "version": "0.57.0-rc.4", + "version": "0.57.0-rc.3", "description": "A framework for building native apps using React", "license": "MIT", "repository": { From fd2db954817f71817485c82c31a2a8f458190cfe Mon Sep 17 00:00:00 2001 From: Hector Ramos Date: Thu, 6 Sep 2018 16:12:51 -0700 Subject: [PATCH 120/273] Remove test dep on publish --- .circleci/config.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 475c3a676e23be..b284b9a3c05ce0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -678,10 +678,6 @@ workflows: - /.*-stable/ tags: only: /v[0-9]+(\.[0-9]+)*(\-rc(\.[0-9]+)?)?/ - requires: - - test_javascript - - test_objc - - test_android # Run code checks - analyze_pr: From 8402c97f83fb100326fe342e54be3e0ab9c27fae Mon Sep 17 00:00:00 2001 From: Hector Ramos Date: Thu, 6 Sep 2018 16:13:03 -0700 Subject: [PATCH 121/273] [0.57.0-rc.4] Bump version numbers --- Libraries/Core/ReactNativeVersion.js | 2 +- React/Base/RCTVersion.m | 2 +- ReactAndroid/gradle.properties | 2 +- .../facebook/react/modules/systeminfo/ReactNativeVersion.java | 2 +- package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Libraries/Core/ReactNativeVersion.js b/Libraries/Core/ReactNativeVersion.js index 92bc60f7c3cf90..f29a91f582c6ca 100644 --- a/Libraries/Core/ReactNativeVersion.js +++ b/Libraries/Core/ReactNativeVersion.js @@ -13,5 +13,5 @@ exports.version = { major: 0, minor: 57, patch: 0, - prerelease: 'rc.3', + prerelease: 'rc.4', }; diff --git a/React/Base/RCTVersion.m b/React/Base/RCTVersion.m index f59421c81f430a..d3cbd0481e1154 100644 --- a/React/Base/RCTVersion.m +++ b/React/Base/RCTVersion.m @@ -23,7 +23,7 @@ static void __makeVersion() RCTVersionMajor: @(0), RCTVersionMinor: @(57), RCTVersionPatch: @(0), - RCTVersionPrerelease: @"rc.3", + RCTVersionPrerelease: @"rc.4", }; } diff --git a/ReactAndroid/gradle.properties b/ReactAndroid/gradle.properties index 0db23518d6c6bf..2c70bc5d009dcd 100644 --- a/ReactAndroid/gradle.properties +++ b/ReactAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=0.57.0-rc.3 +VERSION_NAME=0.57.0-rc.4 GROUP=com.facebook.react POM_NAME=ReactNative diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java index 2500c2abc2ff46..308b0328bd26dd 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java @@ -18,5 +18,5 @@ public class ReactNativeVersion { "major", 0, "minor", 57, "patch", 0, - "prerelease", "rc.3"); + "prerelease", "rc.4"); } diff --git a/package.json b/package.json index 21bb3bae0bde3a..e4297b6513242b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native", - "version": "0.57.0-rc.3", + "version": "0.57.0-rc.4", "description": "A framework for building native apps using React", "license": "MIT", "repository": { From a88243a7631e3b588cca9da080c3ed250e89e51a Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Sun, 2 Sep 2018 12:16:47 -0700 Subject: [PATCH 122/273] React: Upgrade to react-devtools@3.3.2 Summary: Upgrades `react-devtools` for React Native and Nuclide to v3.3.2. Reviewed By: bvaughn Differential Revision: D9565574 fbshipit-source-id: 320b21edee3bcf9b4541ca4936461cdb6f1373e1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e4297b6513242b..aeca9313381487 100644 --- a/package.json +++ b/package.json @@ -188,7 +188,7 @@ "promise": "^7.1.1", "prop-types": "^15.5.8", "react-clone-referenced-element": "^1.0.1", - "react-devtools-core": "^3.2.2", + "react-devtools-core": "3.3.2", "react-timer-mixin": "^0.13.2", "regenerator-runtime": "^0.11.0", "rimraf": "^2.5.4", From 3c1ffd81c7d4f7c7f77e82f32753ccae3c68a0b5 Mon Sep 17 00:00:00 2001 From: Mike Grabowski Date: Mon, 10 Sep 2018 12:53:41 +0200 Subject: [PATCH 123/273] Fix Metro version --- local-cli/init/init.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local-cli/init/init.js b/local-cli/init/init.js index 54324c152ab14d..24446fcee076e5 100644 --- a/local-cli/init/init.js +++ b/local-cli/init/init.js @@ -99,7 +99,7 @@ function generateProject(destinationRoot, newProjectName, options) { }); } if (!options['skip-jest']) { - const jestDeps = `jest babel-jest metro-react-native-babel-preset@^0.43.5 react-test-renderer@${reactVersion}`; + const jestDeps = `jest babel-jest metro-react-native-babel-preset react-test-renderer@${reactVersion}`; if (yarnVersion) { console.log('Adding Jest...'); execSync(`yarn add ${jestDeps} --dev --exact`, {stdio: 'inherit'}); From cbad15863d0cf74ed9329ef0282c072962aa4c37 Mon Sep 17 00:00:00 2001 From: Eli White Date: Wed, 22 Aug 2018 12:49:15 -0700 Subject: [PATCH 124/273] Adding a more complete type for ReactNativeBaseComponentViewConfig Summary: As we add js view configs to our view managers, we want this type to be a little bit more strict. This will be especially useful as we start removing certain keys (like NativeProps) which aren't actually necessary, this will make sure we remove them everywhere. Reviewed By: yungsters Differential Revision: D9416905 fbshipit-source-id: 6b12e38b9d56969a81ec5d4f2920298e4919f7be --- Libraries/Renderer/shims/ReactNativeTypes.js | 41 +++++++++++++++++--- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/Libraries/Renderer/shims/ReactNativeTypes.js b/Libraries/Renderer/shims/ReactNativeTypes.js index 991aa338e77016..2dce8ce507f61e 100644 --- a/Libraries/Renderer/shims/ReactNativeTypes.js +++ b/Libraries/Renderer/shims/ReactNativeTypes.js @@ -44,13 +44,42 @@ type DirectEventType = { registrationName: string, }; -export type ReactNativeBaseComponentViewConfig = { - validAttributes: Object, +type AttributeType = + | true + | $ReadOnly<{| + diff: ?(arg1: T, arg2: T) => boolean, + process: ?(arg1: any) => any, + |}>; + +export type ReactNativeBaseComponentViewConfig = $ReadOnly<{| + baseModuleName?: string, + bubblingEventTypes?: $ReadOnly<{ + [eventName: string]: $ReadOnly<{| + phasedRegistrationNames: $ReadOnly<{| + captured: string, + bubbled: string, + |}>, + |}>, + }>, + Commands?: $ReadOnly<{ + [commandName: string]: number, + }>, + directEventTypes?: $ReadOnly<{ + [eventName: string]: $ReadOnly<{| + registrationName: string, + |}>, + }>, + NativeProps?: $ReadOnly<{ + [propName: string]: string, + }>, uiViewClassName: string, - bubblingEventTypes?: {[topLevelType: string]: BubblingEventType}, - directEventTypes?: {[topLevelType: string]: DirectEventType}, - propTypes?: Object, -}; + validAttributes: $ReadOnly<{ + [propName: string]: AttributeType, + style: $ReadOnly<{ + [propName: string]: AttributeType, + }>, + }>, +|}>; export type ViewConfigGetter = () => ReactNativeBaseComponentViewConfig; From 3ccc141115cb92757fe50be024a3e6203ad47557 Mon Sep 17 00:00:00 2001 From: Eli White Date: Wed, 22 Aug 2018 12:49:14 -0700 Subject: [PATCH 125/273] Put View ViewConfig in JS Summary: Moving this config to native for android so we skip the native lookup for the config. Reviewed By: yungsters Differential Revision: D9415726 fbshipit-source-id: 84cac3f0dfa4f6ea8800de77676f1e2896ee463d --- .../Components/View/ViewNativeComponent.js | 16 +- .../View/ViewNativeComponentAndroidConfig.js | 278 ++++++++++++++++++ 2 files changed, 290 insertions(+), 4 deletions(-) create mode 100644 Libraries/Components/View/ViewNativeComponentAndroidConfig.js diff --git a/Libraries/Components/View/ViewNativeComponent.js b/Libraries/Components/View/ViewNativeComponent.js index 728e81beb419cb..00c58a12189fde 100644 --- a/Libraries/Components/View/ViewNativeComponent.js +++ b/Libraries/Components/View/ViewNativeComponent.js @@ -10,16 +10,24 @@ 'use strict'; +const Platform = require('Platform'); const ReactNative = require('ReactNative'); const requireNativeComponent = require('requireNativeComponent'); +const ReactNativeViewConfigRegistry = require('ReactNativeViewConfigRegistry'); import type {ViewProps} from 'ViewPropTypes'; type ViewNativeComponentType = Class>; -const ViewNativeComponent = ((requireNativeComponent( - 'RCTView', -): any): ViewNativeComponentType); +let NativeViewComponent; -module.exports = ViewNativeComponent; +if (Platform.OS === 'Android') { + NativeViewComponent = ReactNativeViewConfigRegistry.register('RCTView', () => + require('ViewNativeComponentAndroidConfig'), + ); +} else { + NativeViewComponent = requireNativeComponent('RCTView'); +} + +module.exports = ((NativeViewComponent: any): ViewNativeComponentType); diff --git a/Libraries/Components/View/ViewNativeComponentAndroidConfig.js b/Libraries/Components/View/ViewNativeComponentAndroidConfig.js new file mode 100644 index 00000000000000..b53932025a55dc --- /dev/null +++ b/Libraries/Components/View/ViewNativeComponentAndroidConfig.js @@ -0,0 +1,278 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow + */ + +'use strict'; + +const ReactNativeStyleAttributes = require('ReactNativeStyleAttributes'); + +const processColor = require('processColor'); + +const colorHandler = {diff: null, process: processColor}; + +const ViewNativeComponentAndroidConfig = { + bubblingEventTypes: { + topChange: { + phasedRegistrationNames: { + captured: 'onChangeCapture', + bubbled: 'onChange', + }, + }, + topTouchCancel: { + phasedRegistrationNames: { + captured: 'onTouchCancelCapture', + bubbled: 'onTouchCancel', + }, + }, + topTouchMove: { + phasedRegistrationNames: { + captured: 'onTouchMoveCapture', + bubbled: 'onTouchMove', + }, + }, + topTouchStart: { + phasedRegistrationNames: { + captured: 'onTouchStartCapture', + bubbled: 'onTouchStart', + }, + }, + topTouchEnd: { + phasedRegistrationNames: { + captured: 'onTouchEndCapture', + bubbled: 'onTouchEnd', + }, + }, + topSelect: { + phasedRegistrationNames: { + captured: 'onSelectCapture', + bubbled: 'onSelect', + }, + }, + }, + Commands: {setPressed: 2, hotspotUpdate: 1}, + directEventTypes: { + topLoadingError: {registrationName: 'onLoadingError'}, + topLayout: {registrationName: 'onLayout'}, + topScrollBeginDrag: {registrationName: 'onScrollBeginDrag'}, + topContentSizeChange: {registrationName: 'onContentSizeChange'}, + topMomentumScrollBegin: {registrationName: 'onMomentumScrollBegin'}, + topScrollEndDrag: {registrationName: 'onScrollEndDrag'}, + topMomentumScrollEnd: {registrationName: 'onMomentumScrollEnd'}, + topLoadingStart: {registrationName: 'onLoadingStart'}, + topSelectionChange: {registrationName: 'onSelectionChange'}, + topLoadingFinish: {registrationName: 'onLoadingFinish'}, + topMessage: {registrationName: 'onMessage'}, + topScroll: {registrationName: 'onScroll'}, + }, + NativeProps: { + accessibilityComponentType: 'String', + accessibilityHint: 'String', + accessibilityLabel: 'String', + accessibilityLiveRegion: 'String', + accessibilityRole: 'String', + accessibilityStates: 'Array', + accessible: 'boolean', + alignContent: 'String', + alignItems: 'String', + alignSelf: 'String', + aspectRatio: 'number', + backgroundColor: 'Color', + borderBottomColor: 'Color', + borderBottomEndRadius: 'number', + borderBottomLeftRadius: 'number', + borderBottomRightRadius: 'number', + borderBottomStartRadius: 'number', + borderBottomWidth: 'number', + borderColor: 'Color', + borderEndColor: 'Color', + borderEndWidth: 'number', + borderLeftColor: 'Color', + borderLeftWidth: 'number', + borderRadius: 'number', + borderRightColor: 'Color', + borderRightWidth: 'number', + borderStartColor: 'Color', + borderStartWidth: 'number', + borderStyle: 'String', + borderTopColor: 'Color', + borderTopEndRadius: 'number', + borderTopLeftRadius: 'number', + borderTopRightRadius: 'number', + borderTopStartRadius: 'number', + borderTopWidth: 'number', + borderWidth: 'number', + bottom: 'Dynamic', + collapsable: 'boolean', + display: 'String', + elevation: 'number', + end: 'Dynamic', + flex: 'number', + flexBasis: 'Dynamic', + flexDirection: 'String', + flexGrow: 'number', + flexShrink: 'number', + flexWrap: 'String', + hasTVPreferredFocus: 'boolean', + height: 'Dynamic', + hitSlop: 'Map', + importantForAccessibility: 'String', + justifyContent: 'String', + left: 'Dynamic', + margin: 'Dynamic', + marginBottom: 'Dynamic', + marginEnd: 'Dynamic', + marginHorizontal: 'Dynamic', + marginLeft: 'Dynamic', + marginRight: 'Dynamic', + marginStart: 'Dynamic', + marginTop: 'Dynamic', + marginVertical: 'Dynamic', + maxHeight: 'Dynamic', + maxWidth: 'Dynamic', + minHeight: 'Dynamic', + minWidth: 'Dynamic', + nativeBackgroundAndroid: 'Map', + nativeForegroundAndroid: 'Map', + nativeID: 'String', + needsOffscreenAlphaCompositing: 'boolean', + onLayout: 'boolean', + opacity: 'number', + overflow: 'String', + padding: 'Dynamic', + paddingBottom: 'Dynamic', + paddingEnd: 'Dynamic', + paddingHorizontal: 'Dynamic', + paddingLeft: 'Dynamic', + paddingRight: 'Dynamic', + paddingStart: 'Dynamic', + paddingTop: 'Dynamic', + paddingVertical: 'Dynamic', + pointerEvents: 'String', + position: 'String', + removeClippedSubviews: 'boolean', + renderToHardwareTextureAndroid: 'boolean', + right: 'Dynamic', + rotation: 'number', + scaleX: 'number', + scaleY: 'number', + start: 'Dynamic', + testID: 'String', + top: 'Dynamic', + transform: 'Array', + translateX: 'number', + translateY: 'number', + width: 'Dynamic', + zIndex: 'number', + }, + + uiViewClassName: 'RCTView', + validAttributes: { + accessibilityComponentType: true, + accessibilityHint: true, + accessibilityLabel: true, + accessibilityLiveRegion: true, + accessibilityRole: true, + accessibilityStates: true, + accessible: true, + alignContent: true, + alignItems: true, + alignSelf: true, + aspectRatio: true, + backgroundColor: colorHandler, + borderBottomColor: colorHandler, + borderBottomEndRadius: true, + borderBottomLeftRadius: true, + borderBottomRightRadius: true, + borderBottomStartRadius: true, + borderBottomWidth: true, + borderColor: colorHandler, + borderEndColor: colorHandler, + borderEndWidth: true, + borderLeftColor: colorHandler, + borderLeftWidth: true, + borderRadius: true, + borderRightColor: colorHandler, + borderRightWidth: true, + borderStartColor: colorHandler, + borderStartWidth: true, + borderStyle: true, + borderTopColor: colorHandler, + borderTopEndRadius: true, + borderTopLeftRadius: true, + borderTopRightRadius: true, + borderTopStartRadius: true, + borderTopWidth: true, + borderWidth: true, + bottom: true, + collapsable: true, + display: true, + elevation: true, + end: true, + flex: true, + flexBasis: true, + flexDirection: true, + flexGrow: true, + flexShrink: true, + flexWrap: true, + hasTVPreferredFocus: true, + height: true, + hitSlop: true, + importantForAccessibility: true, + justifyContent: true, + left: true, + margin: true, + marginBottom: true, + marginEnd: true, + marginHorizontal: true, + marginLeft: true, + marginRight: true, + marginStart: true, + marginTop: true, + marginVertical: true, + maxHeight: true, + maxWidth: true, + minHeight: true, + minWidth: true, + nativeBackgroundAndroid: true, + nativeForegroundAndroid: true, + nativeID: true, + needsOffscreenAlphaCompositing: true, + onLayout: true, + opacity: true, + overflow: true, + padding: true, + paddingBottom: true, + paddingEnd: true, + paddingHorizontal: true, + paddingLeft: true, + paddingRight: true, + paddingStart: true, + paddingTop: true, + paddingVertical: true, + pointerEvents: true, + position: true, + removeClippedSubviews: true, + renderToHardwareTextureAndroid: true, + right: true, + rotation: true, + scaleX: true, + scaleY: true, + start: true, + testID: true, + top: true, + transform: true, + translateX: true, + translateY: true, + width: true, + zIndex: true, + style: ReactNativeStyleAttributes, + }, +}; + +module.exports = ViewNativeComponentAndroidConfig; From 7b1186c05a70a5cafb0612e59aebede97a8d3a81 Mon Sep 17 00:00:00 2001 From: Eli White Date: Wed, 22 Aug 2018 12:49:18 -0700 Subject: [PATCH 126/273] Require all Android View Attributes are defined in flow prop types Summary: This caught a few flow types that weren't defined for attributes that Android exposes. Ensuring that these stay in sync will be necessary for codegen in the future. Reviewed By: sahrens Differential Revision: D9444165 fbshipit-source-id: 8ee00af7b732c35d7f6befcdf79f77b73eac6a1b --- .../View/ViewNativeComponentAndroidConfig.js | 11 ++++++++++- Libraries/Components/View/ViewPropTypes.js | 17 +++++++++++++++++ Libraries/Renderer/shims/ReactNativeTypes.js | 11 +++++++---- .../shims/ReactNativeViewConfigRegistry.js | 4 ++-- 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/Libraries/Components/View/ViewNativeComponentAndroidConfig.js b/Libraries/Components/View/ViewNativeComponentAndroidConfig.js index b53932025a55dc..b0fdf87f960f25 100644 --- a/Libraries/Components/View/ViewNativeComponentAndroidConfig.js +++ b/Libraries/Components/View/ViewNativeComponentAndroidConfig.js @@ -14,9 +14,18 @@ const ReactNativeStyleAttributes = require('ReactNativeStyleAttributes'); const processColor = require('processColor'); +import type {ViewProps} from 'ViewPropTypes'; +import type {____ViewStyle_Internal} from 'StyleSheetTypes'; +import type {ReactNativeBaseComponentViewConfig} from 'ReactNativeTypes'; + const colorHandler = {diff: null, process: processColor}; -const ViewNativeComponentAndroidConfig = { +type Config = ReactNativeBaseComponentViewConfig< + $Keys | $Keys<____ViewStyle_Internal>, + $Keys<____ViewStyle_Internal>, +>; + +const ViewNativeComponentAndroidConfig: Config = { bubblingEventTypes: { topChange: { phasedRegistrationNames: { diff --git a/Libraries/Components/View/ViewPropTypes.js b/Libraries/Components/View/ViewPropTypes.js index 238017cf187121..9ce73cb344fbcf 100644 --- a/Libraries/Components/View/ViewPropTypes.js +++ b/Libraries/Components/View/ViewPropTypes.js @@ -71,10 +71,27 @@ type GestureResponderEventProps = $ReadOnly<{| onStartShouldSetResponderCapture?: ?Function, |}>; +type AndroidViewProps = $ReadOnly<{| + nativeBackgroundAndroid?: ?Object, + nativeForegroundAndroid?: ?Object, + + /* Deprecated transform prop. Use the transform style prop instead */ + rotation?: empty, + /* Deprecated transform prop. Use the transform style prop instead */ + scaleX?: empty, + /* Deprecated transform prop. Use the transform style prop instead */ + scaleY?: empty, + /* Deprecated transform prop. Use the transform style prop instead */ + translateX?: empty, + /* Deprecated transform prop. Use the transform style prop instead */ + translateY?: empty, +|}>; + export type ViewProps = $ReadOnly<{| ...DirectEventProps, ...GestureResponderEventProps, ...TouchEventProps, + ...AndroidViewProps, // There's no easy way to create a different type if (Platform.isTV): // so we must include TVViewProps diff --git a/Libraries/Renderer/shims/ReactNativeTypes.js b/Libraries/Renderer/shims/ReactNativeTypes.js index 2dce8ce507f61e..1ee89e82dab9f8 100644 --- a/Libraries/Renderer/shims/ReactNativeTypes.js +++ b/Libraries/Renderer/shims/ReactNativeTypes.js @@ -51,7 +51,10 @@ type AttributeType = process: ?(arg1: any) => any, |}>; -export type ReactNativeBaseComponentViewConfig = $ReadOnly<{| +export type ReactNativeBaseComponentViewConfig< + TProps = string, + TStyleProps = string, +> = $ReadOnly<{| baseModuleName?: string, bubblingEventTypes?: $ReadOnly<{ [eventName: string]: $ReadOnly<{| @@ -74,14 +77,14 @@ export type ReactNativeBaseComponentViewConfig = $ReadOnly<{| }>, uiViewClassName: string, validAttributes: $ReadOnly<{ - [propName: string]: AttributeType, + [propName: TProps]: AttributeType, style: $ReadOnly<{ - [propName: string]: AttributeType, + [propName: TStyleProps]: AttributeType, }>, }>, |}>; -export type ViewConfigGetter = () => ReactNativeBaseComponentViewConfig; +export type ViewConfigGetter = () => ReactNativeBaseComponentViewConfig<>; /** * Class only exists for its Flow type. diff --git a/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js b/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js index 1ef2e80e371a44..cb16c50f514c99 100644 --- a/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js +++ b/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js @@ -30,7 +30,7 @@ const viewConfigCallbacks = new Map(); const viewConfigs = new Map(); function processEventTypes( - viewConfig: ReactNativeBaseComponentViewConfig, + viewConfig: ReactNativeBaseComponentViewConfig<>, ): void { const {bubblingEventTypes, directEventTypes} = viewConfig; @@ -86,7 +86,7 @@ exports.register = function(name: string, callback: ViewConfigGetter): string { * If this is the first time the view has been used, * This configuration will be lazy-loaded from UIManager. */ -exports.get = function(name: string): ReactNativeBaseComponentViewConfig { +exports.get = function(name: string): ReactNativeBaseComponentViewConfig<> { let viewConfig; if (!viewConfigs.has(name)) { const callback = viewConfigCallbacks.get(name); From 0b30129cde080c1555f07ddc8853e03fe9fcf607 Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Mon, 10 Sep 2018 14:42:08 -0700 Subject: [PATCH 127/273] React sync for revisions bc1ea9c...ade5e69 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: This sync includes the following changes: - **[ade5e6928](https://github.com/facebook/react/commit/ade5e6928)**: Manually update schedule dep in react-native-renderer (#13609) //// - **[f260b14a8](https://github.com/facebook/react/commit/f260b14a8)**: Fix host bailout for the persistent mode (#13611) //// - **[4a40d7624](https://github.com/facebook/react/commit/4a40d7624)**: Fix a regression related to isReactComponent prototype check (#13608) //// - **[03ab1efeb](https://github.com/facebook/react/commit/03ab1efeb)**: Improve DX when combining react-dom/profiling and schedule/tracking (#13605) //// - **[144328fe8](https://github.com/facebook/react/commit/144328fe8)**: Enable no-use-before-define rule (#13606) //// - **[8a8d973d3](https://github.com/facebook/react/commit/8a8d973d3)**: Use clearer wording //// - **[7d1169b2d](https://github.com/facebook/react/commit/7d1169b2d)**: Remove injectComponentTree from unstable-native-dependencies, add EventPluginHub (#13598) //// - **[8d1038fc6](https://github.com/facebook/react/commit/8d1038fc6)**: Break up ReactDOMServerIntegrationForm-test (#13600) //// - **[b87aabdfe](https://github.com/facebook/react/commit/b87aabdfe)**: Drop the year from Facebook copyright headers and the LICENSE file. (#13593) //// - **[e417e0bf7](https://github.com/facebook/react/commit/e417e0bf7)**: Update ReactNativeViewConfigRegistry Flow Types (#13579) //// - **[71c0e05ba](https://github.com/facebook/react/commit/71c0e05ba)**: Update bundle sizes for 16.5.0 release //// - **[6255cc394](https://github.com/facebook/react/commit/6255cc394)**: Updating package versions for release 16.5.0 //// - **[28cb37978](https://github.com/facebook/react/commit/28cb37978)**: Added a test for Profiler onRender that throws (#13575) //// - **[8963118b3](https://github.com/facebook/react/commit/8963118b3)**: Update react-dom README //// - **[b47a28cb9](https://github.com/facebook/react/commit/b47a28cb9)**: Tweak react-dom README //// - **[f765f0225](https://github.com/facebook/react/commit/f765f0225)**: When a root expires, flush all expired work in a single batch (#13503) //// - **[550dd1d2e](https://github.com/facebook/react/commit/550dd1d2e)**: Call Profiler onRender after mutations (#13572) //// - **[34348a45b](https://github.com/facebook/react/commit/34348a45b)**: Add enableSuspenseServerRenderer feature flag (#13573) //// - **[4e744be6e](https://github.com/facebook/react/commit/4e744be6e)**: Added react-dom/profiling entry point to NPM package (#13570) //// - **[bb627228e](https://github.com/facebook/react/commit/bb627228e)**: test: add test for fragement props (#13565) //// - **[9a110ebd8](https://github.com/facebook/react/commit/9a110ebd8)**: Cleaned up 'schedule' API wrt interactions and subscriber ref: (#13561) //// - **[fb88fd9d8](https://github.com/facebook/react/commit/fb88fd9d8)**: Fixed schedule/tracking require for www sync script (#13556) //// - **[955393cab](https://github.com/facebook/react/commit/955393cab)**: refactor: remove emove type judgment when defining warning props (#13553) //// - **[ff9399602](https://github.com/facebook/react/commit/ff9399602)**: Fix import of ReactDOM in server env //// - **[281bd64c0](https://github.com/facebook/react/commit/281bd64c0)**: Fix test file name //// - **[d6b59e3d2](https://github.com/facebook/react/commit/d6b59e3d2)**: Check document.documentMode once //// - **[52633c84e](https://github.com/facebook/react/commit/52633c84e)**: Try/finally //// - **[2d4705e75](https://github.com/facebook/react/commit/2d4705e75)**: Make IE 11 not complain about non-crucial style attribute hydration mismatch (#13534) //// - **[25d48a728](https://github.com/facebook/react/commit/25d48a728)**: Add gridArea to unitless CSS properties (#13550) //// - **[877f8bc6b](https://github.com/facebook/react/commit/877f8bc6b)**: Renamed schedule UMD forwarding methods to stay in-sync with SECRET_INTERNALS change (#13549) //// - **[0a96f9057](https://github.com/facebook/react/commit/0a96f9057)**: Revert "Extract common logic" (#13547) //// - **[17a57adde](https://github.com/facebook/react/commit/17a57adde)**: Fix test //// - **[605da8b42](https://github.com/facebook/react/commit/605da8b42)**: Extract common logic (#13535) //// - **[69f9f4127](https://github.com/facebook/react/commit/69f9f4127)**: Document event bubble order (#13546) //// - **[c1ba7b8cf](https://github.com/facebook/react/commit/c1ba7b8cf)**: Remove www scheduler fork (#13545) //// - **[b473d5f86](https://github.com/facebook/react/commit/b473d5f86)**: Secret exports: Scheduler => Schedule (#13544) //// - **[6312efc34](https://github.com/facebook/react/commit/6312efc34)**: Tweak README and description //// - **[b92f947af](https://github.com/facebook/react/commit/b92f947af)**: Rename "react-scheduler" package to "schedule" (#13543) //// - **[3c1dcd349](https://github.com/facebook/react/commit/3c1dcd349)**: Expose less internals for TestUtils (#13539) //// - **[0b74e95d7](https://github.com/facebook/react/commit/0b74e95d7)**: Ignore noscript content on the client (#13537) //// - **[8a1e3962a](https://github.com/facebook/react/commit/8a1e3962a)**: Remove negative lookbehind from Rollup plugin that broke Node <= v8.9 (#13538) //// - **[9604d26ae](https://github.com/facebook/react/commit/9604d26ae)**: Rename ReactDOMFiber* to ReactDOM* (#13540) //// - **[28b928902](https://github.com/facebook/react/commit/28b928902)**: Tidied up scheduling UMD API forwarding test (#13533) //// - **[bf8aa6092](https://github.com/facebook/react/commit/bf8aa6092)**: Added Jest test to verify UMD API-forwarding for scheduling package (#13532) //// - **[0040efc8d](https://github.com/facebook/react/commit/0040efc8d)**: Fix a typo (#13531) //// - **[46950a3df](https://github.com/facebook/react/commit/46950a3df)**: Interaction tracking follow up (#13509) //// - **[0452c9bba](https://github.com/facebook/react/commit/0452c9bba)**: Add a regression test for #4618 //// - **[c21bab694](https://github.com/facebook/react/commit/c21bab694)**: Add SSR regression test for #6119 //// - **[0d3fc9de1](https://github.com/facebook/react/commit/0d3fc9de1)**: Add regression test for #6119 //// - **[0f050ad7c](https://github.com/facebook/react/commit/0f050ad7c)**: Make regression test better //// - **[f94342323](https://github.com/facebook/react/commit/f94342323)**: Add a more precise regression test for #6219 //// - **[a3e4d0008](https://github.com/facebook/react/commit/a3e4d0008)**: Fixed typo (#13519) //// - **[b3d8c5376](https://github.com/facebook/react/commit/b3d8c5376)**: [RN] Remove isMounted() false positive warning (#13511) //// - **[d2123d656](https://github.com/facebook/react/commit/d2123d656)**: Sync React Native Flow Changes (#13513) //// - **[1c0ba70b4](https://github.com/facebook/react/commit/1c0ba70b4)**: Fix test to use AsyncMode //// - **[6e4f7c788](https://github.com/facebook/react/commit/6e4f7c788)**: Profiler integration with interaction-tracking package (#13253) //// - **[2967ebdbe](https://github.com/facebook/react/commit/2967ebdbe)**: Remove buggy unstable_deferredUpdates() (#13488) //// - **[1664b08f0](https://github.com/facebook/react/commit/1664b08f0)**: added flow types to setInnerHTML (#13495) //// - **[672e859d3](https://github.com/facebook/react/commit/672e859d3)**: Add warning to prevent setting this.state to this.props referentially (#11658) //// - **[29287f088](https://github.com/facebook/react/commit/29287f088)**: Rename lowestPendingInteractiveExpirationTime (#13484) //// - **[d400d6d5e](https://github.com/facebook/react/commit/d400d6d5e)**: Replace magic number 1 with ELEMENT_NODE (#13479) //// - **[340bfd939](https://github.com/facebook/react/commit/340bfd939)**: Rename ReactTypeOfWork to ReactWorkTags, ReactTypeOfSideEffect to ReactSideEffectTags (#13476) //// - **[5cefd9b1e](https://github.com/facebook/react/commit/5cefd9b1e)**: Stringify